黑白球
提示一下:这道题有可能会让你做的怀疑人生,所以,准备好武器......
题目:
LQX在高老师不在的一天当中发明了一个小游戏:将若干黑色和白色的乒乓球摆成一列。现在他想按顺序(分组时只能按照从左往右的顺序取)将这些乒乓球分成若组,使得每组的白球和黑球的比例相同。
当然,他可以把所有的球直接作为一组,但是那样你就太鄙视LQX的智商了。为了增加难度,他想知道最多能分成多少组,例如,如果用0表示白球,1表示黑球的话,那么:
100011 = 10+0011(样例1,最多分成两组,比例为1:1)
0001110000000001 = 0001+11000000+0001(样例2,最多分成3组,比例为3:1)
输入:
第一行输入一个整数N,表示将用N行来描述这一列乒乓球。
以下N行,每行包含两个用空格隔开的整数Ki和Ci,Ci只可能是0或1,表示在上一行结束后尾部又有了Ki个颜色为Ci的乒乓球。
注意:连续几行的Ci可能相同。
输出:
一行一个数,表示最多可以分的组数。
数据范围:
N<=10^5
乒乓球数量<=10^9
题解:由于比例的可加减性(1:2+1:2+1:2=1:2),也就是说,总比例等于分出来后的比例,只用先算出来总共的黑白比例,再挨个找就行了,嗯,不过这样只能的40分,因为乒乓球数量<=10^9,时间超限!!!还有一种方法,每次直接加k[i],如果加之前小,加之后大,并且比例内向积%外向的一个数,为0,ans++;最后就可以输出ans;
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> using namespace std; long long sum[2]; int zhan(int x,int y)//辗转相除 { if(y==0) return x; return zhan(y,x%y); } long ans; long k[100001],c[100001]; long long now[2]; int main() { int n; cin>>n; for(int i=1;i<=n;i++) { scanf("%d%d",&k[i],&c[i]); sum[c[i]]+=k[i]; } if(min(sum[0],sum[1])==0) { cout<<max(sum[0],sum[1]); return 0; } long long p=zhan(sum[0],sum[1]); sum[0]/=p; sum[1]/=p; for(int i=1;i<=n;i++) { if(sum[1]*now[0]==sum[0]*now[1]) { ans++; } if(c[i]) { if(sum[1]*now[0]<(now[1]+k[i])*sum[0] && sum[1]*now[0]>now[1]*sum[0])//判断1 { if((sum[1]*now[0])%sum[0]==0)//判断2 { ans++; } } now[1]+=k[i];//加 } else { if(sum[0]*now[1]<(now[0]+k[i])*sum[1] && sum[0]*now[1]>now[0]*sum[1]) { if((sum[0]*now[1])%sum[1]==0) { ans++; } } now[0]+=k[i]; } } cout<<ans;//输出 return 0; }