感悟:这次比赛AC了第一题和最后一题,感觉最近都快疯了,哈哈哈~
Press the Button这道题题目是读懂了,直接遍历的话肯定会超时,当时我们抱着侥幸心态,交了一发,果然超时。当然,我们推出最小公倍数是它的循环节。当时分析的最坏情况下的时间复杂度,不足以应对这道题,便舍弃了这道题。赛后却发现这竟然是正解,excuse me~
ZOJ4047 Live love (水~)
题意:
一个序列里有n个数,分为完美数和不完美数,其中完美数有m个,那么不完美数有n-m个。分数就是序列中完美数连续的最大长度。给定n和m,求所有情况中的最高分Smax和最低分Smin。
题解:
显然,题目中所求的最高分就是完美数最集中的时候,即m个全部连续在一起;最低分就是完美数分散得最均匀,也就是n-m个不完美数均匀插在m个完美数之间,将完美数分成n-m+1块,那么在这些块中,连续完美数的最大长度是m/(n-m+1)上取整,即得分为m/(n-m+1)上取整。
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int main(){ int t,n,m; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); printf("%d %d\n",m,(int)ceil(1.0*m/(n-m+1))); } return 0; }
ZOJ4057 XOR Clique (水~)
题意:
给定一个有n个数的序列,让你找出一个集合,这个集合满足这样一个条件:任意两个数异或的结果均小于这两个数中的最小值,问这样的集合最大包含几个数?
题解:
最后我们找出规律发现,只要二进制位数一样,尽可以满足上式。
首先看数据量1e5,若要暴力的话,时间复杂度要大于O(n^n),1e10肯定会超时(时间复杂度1e6的话,轻轻松松;1e7,勉勉强强;1e8,可以放弃了)。
例如,7和8异或,化成二进制
0111 //二进制3位
1000 //二进制4位
1111
显然,异或结果大于其中的最小值;
8和11,化成二进制
1000 //二进制4位
1011 //二进制4位
0011
这样的是满足的。
只要集合中每个数对应的二进制位数一样,都可以满足任意两个数异或的结果均小于这两个数中的最小值。
异或:两个二进制的同一位,相同为0,不同为1。
log():以e为底;
log10():以10为底;
log2():以2为底。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn=1e5+10; int a[maxn]; int main(){ int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); a[i]=(int)(log(a[i]*1.0)/log(2.0)); } sort(a+1,a+1+n); int cnt=1,ans=1; for(int i=2;i<=n;i++){ if(a[i]==a[i-1]) cnt++; else{ ans=max(ans,cnt); cnt=1; } } ans=max(ans,cnt); printf("%d\n",ans); } return 0; }