黑白球

提示一下:这道题有可能会让你做的怀疑人生,所以,准备好武器......

题目:

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;
}
原文地址:https://www.cnblogs.com/chen-1/p/9466699.html