NOIP2016 T4 魔法阵 暴力枚举+前缀和后缀和优化
想把最近几年的NOIP T4都先干掉,就大概差16年的,所以来做一做。
然后这题就浪费了我一整天QAQ...果然还是自己太弱了QAQ
还是pa洛谷的...
题意:给m个物品,每个物品有一个不超过n的数xi。
如果存在四元组 (a,b,c,d)满足
① xa<xb<xc<xd
② xb-xa=2(xd-xc)
③ xb-xa<(xc-xb)/3
辣么这个四元组是有效的,问每个物品分别作为有效四元组中 a,b,c,d 几次
思路:16年是第一次参加的noip啊...结果炸的挺惨的,比赛的时候这题没多少时间打了,就草草打了一个暴力优化,结果细节没考虑挂掉了。
今天再来写的时候先敲了暴力,一个简单的暴力优化可以水到85分,所以真的是暴力出奇迹啊=v=
辣正解捏,不得不说这题的数学成分实在太高,我想了整整一个下午都没搞懂,但其实真的不是很难吧...
我们可以这样去想,把每一个物品的数字都抽象为一个数轴上的点的坐标。
然后画图。
可以这样考虑,设xd-xc=i 则 xb-xa=2*(xd-xc)=2*i
把化简的二式带入三式 得: 6*i<xc-xb 设6*i+k=xc-xb ( 就是把差的部分补上去,这个姿势貌似还挺有用)
这样的话就可以画图了,由一式条件和化简后的式子可以得到这样的图

图丑就别喷了... 所以 AD=9i+k 所以 i 的取值范围也可以得到 1≤i≤n/9 (准确来说 i 要比n更小,不过没什么影响)
画完图是不是清晰了一点(其实并没有啊)
然后我萌就可以这样想了,如果知道了 i 和 A 就可以得到 B 如果知道 i 和 C 就可以得到 D 但是如果仅知道某两项是得不到其他的。
我萌把A和B看成一个整体,把C和D看成一个整体,并分别求答案。
我萌枚举 i ,然后枚举 A 这样可以算出 B, 同时 我萌可以知道 C 和 D的最小位置 即当 k=1 时 C=A+8i+1,D=A+9i+1, 知道这个最小位置有什么用?
因为知道A的答案=数字为B的物品个数*数字为C的物品个数*数字为D的物品个数
而对于任意k,如果存在数字C的位置有物品且D的位置有物品,辣么很显然 数字为C的物品个数*数字为D的物品个数 可以通过枚举A的过程中利用后缀和进行累积,然后又因为要后缀和,所以A就得从后往前枚举。
B的答案类似,在A进行求答的时候可以一起求了。
B的答案=数字为A的物品个数*数字为C的物品个数*数字为D的物品个数
辣CD为一个整体的时候捏,类比啊,一样的,但是发现数字为A的物品个数*数字为B的物品个数 累积的时候是前缀和了,所以C的枚举就是从前往后。
一道很棒的题,很棒的数学题...(困惑了我好久,看题解还看不懂!!)
var n,m:longint;
a,id,num:array[..]of longint;
l:array[..]of longint;
i,j,k,d:longint;
z:longint;
numab,numcd:longint;
sum:array[..,..]of longint;
begin
read(n,m);
for i:= to m do
begin
read(a[i]);
inc(num[a[i]])
end;
for i:= to (n div ) do
begin
numcd:=;
for j:=n-(*i+) downto do
begin
numcd:=numcd+num[j+*i+]*num[j+*i+];
inc(sum[j,],num[j+*i]*numcd);
inc(sum[j+*i,],num[j]*numcd);
end;
numab:=;
for j:=*i+ to n-i do
begin
numab:=numab+num[j-*i-]*num[j-*i-];
inc(sum[j,],num[j+i]*numab);
inc(sum[j+i,],num[j]*numab);
end;
end;
for i:= to m do
begin
for j:= to do
write(sum[a[i],j],' ');
writeln;
end;
end.
NOIP2016 T4
转c++后重新写了一遍这题,有了更好的理解代码一起pia上来
#include<cstdio>
#define ll long long
using namespace std;
ll ans[][];
int a[],num[];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for (int i=;i<=m;i++){
scanf("%d",&a[i]);
num[a[i]]++;
}
for (int t=;t<=n/;t++){
ll sum=;
for (int i=*t+;i<=n-t;i++){
sum+=1ll*num[i-*t-]*num[i-*t-];
ans[i][]+=sum*num[i]*num[i+t];
ans[i+t][]+=sum*num[i]*num[i+t];
}
sum=;
for (int i=n-*t-;i>*t;i--){
sum+=1ll*num[i+*t+]*num[i+*t+];
ans[i][]+=sum*num[i]*num[i-*t];
ans[i-*t][]+=sum*num[i]*num[i-*t];
}
}
for (int i=;i<=m;i++){
for (int j=;j<=;j++)
printf("%lld ",ans[a[i]][j]/num[a[i]]);
printf("\n");
}
return ;
}
/*
条件① Xa<Xb<Xc<Xd
② Xb-Xa=2(Xd-Xc)
③ Xb-Xa<(Xc-Xb)/3
可以发现Xd-Xc是一个最小单位
设 t=Xd-Xc;
②得Xb-Xa=2t
③得2t<(Xc-Xb)/3 即6t<Xc-Xb
粗略的画图
--------------------
A B------C D
--- >6t ----
t 2t
D最大是n A最小是1
所以t的取值就是
1<=t<=(n-1)/t
粗略的
1<=t<=n/t 因为数组开大后溢出没有任何影响
于是枚举t 再枚举C
D的位置就得到了
而因为BC之间只要大于6t就行。
所以设C1<C2 D1<D2
C1 D1所能匹配的A B C2 D2 也可以
于是满足了前缀和
只要往后枚举C的时候把上一个C的A B组数保存着累加就好了
A B同理,枚举 B,A确定 C D变成了后缀和。
画图把B C的取值范围算一下即可
*/
NOIP2016 T4
果然自己真的要多做题啊QAQ
NOIP2016 T4 魔法阵 暴力枚举+前缀和后缀和优化的更多相关文章
- CodeForces 742B Arpa’s obvious problem and Mehrdad’s terrible solution (暴力枚举)
题意:求定 n 个数,求有多少对数满足,ai^bi = x. 析:暴力枚举就行,n的复杂度. 代码如下: #pragma comment(linker, "/STACK:1024000000 ...
- 2014牡丹江网络赛ZOJPretty Poem(暴力枚举)
/* 将给定的一个字符串分解成ABABA 或者 ABABCAB的形式! 思路:暴力枚举A, B, C串! */ 1 #include<iostream> #include<cstri ...
- HNU 12886 Cracking the Safe(暴力枚举)
题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12886&courseid=274 解题报告:输入4个数 ...
- 51nod 1116 K进制下的大数 (暴力枚举)
题目链接 题意:中文题. 题解:暴力枚举. #include <iostream> #include <cstring> using namespace std; ; ; ch ...
- (算是dp吧) 小茗的魔法阵 (fzu 2225)
http://acm.fzu.edu.cn/problem.php?pid=2225 Problem Description 在打败了易基•普罗布朗.诺姆•普罗布朗之后,小茗同学开始挑战哈德•普罗 ...
- Codeforces Round #349 (Div. 1) B. World Tour 最短路+暴力枚举
题目链接: http://www.codeforces.com/contest/666/problem/B 题意: 给你n个城市,m条单向边,求通过最短路径访问四个不同的点能获得的最大距离,答案输出一 ...
- bzoj 1028 暴力枚举判断
昨天梦到这道题了,所以一定要A掉(其实梦到了3道,有两道记不清了) 暴力枚举等的是哪张牌,将是哪张牌,然后贪心的判断就行了. 对于一个状态判断是否为胡牌,1-n扫一遍,然后对于每个牌,先mod 3, ...
- POJ-3187 Backward Digit Sums (暴力枚举)
http://poj.org/problem?id=3187 给定一个个数n和sum,让你求原始序列,如果有多个输出字典序最小的. 暴力枚举题,枚举生成的每一个全排列,符合即退出. dfs版: #in ...
- hihoCoder #1179 : 永恒游戏 (暴力枚举)
题意: 给出一个有n个点的无向图,每个点上有石头数个,现在的游戏规则是,设置某个点A的度数为d,如果A点的石子数大于等于d,则可以从A点给每个邻接点发一个石子.如果游戏可以玩10万次以上,输出INF, ...
随机推荐
- Android 获取系统默认输入法
import android.provider.Settings; import android.text.TextUtils; 获取默认输入法包名: private String getDefaul ...
- 从一次渗透谈到linux如何反弹shell
零.绪论 背景: ThinkPHP框架的--> 找到一个OS命令注入(很简单的Burp可以直接扫出来的那种):页面配置系统默认网关处. 一.渗透过程 1.首先看了一下,没有回显. 2.用ceye ...
- navigater导航
1.css的hover事件2.url事件(或者click事件),激活当前项3.第一导航与第二导航的移入移出事件(可以通过left,top值来显示,也可以变化宽度,高宽来显示)4.有二级导航的另外给cl ...
- JQuery操作Select标签
jQuery获取Select选择的Text和Value: 1. $("#select_id").change(function(){//code...}); //为Select添加 ...
- 设计模式之一:单例模式(Singleton Pattern)
写这个系列的文章,只为把所学的设计模式再系统的整理一遍.错误和不周到的地方欢迎大家批评.点击这里下载源代码. 什么时候使用单例模式 在程序运行时,某种类型只需要一个实例时,一般采用单例模式.为什么需要 ...
- (转)Python学习路径及练手项目合集
转载自知乎 Wayne Shi,仅仅为了方便收藏查看,侵权删. 阶段1:入门知识 零编程基础的可以先从下面几个教程了解编程及环境入门知识.(已有编程基础直接从阶段2起步) 1. 编程新手指南2. Li ...
- SpringBoot实现热加载方式
一. spring-boot-devtools方式1.在pom.xml中加入以下代码: 2.标识红线的地方加上 3.在设置里面加上自动编译 4.shift+ctrl+alt+/ 这样就可以了! 二.s ...
- CH1402 后缀数组【Hash】【字符串】【二分】
1402 后缀数组 0x10「基本数据结构」例题 描述 后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围.在本题中,我们希望使用快排.Hash与二分实现 ...
- ubuntu下完全卸载opencv3.1.0
在ubuntu下删除opencv需要以下步骤: 1.进入opencv的源代码文件夹下的release(这是你在安装opencv时候自己命名的,cmake时候所在的目录) 2.执行以下命令 sudo m ...
- Oracle 11gR2 RAC监听器原理介绍
一.基本概念 oracle11gR2 RAC开始引入scan概念,一般通过dns服务器或gns服务器解析scan,也可以使用/etc/hosts文件解析scan,只不过oracle官方不建议这样做,h ...