POJ2356Find a multiple

鸽巢原理的应用

我们要从一堆数中找到一堆数的和是n的倍数,暴力枚举显然不可行,怎么办呢?

我们不妨求出这n个数的前缀和,发现在mod n意义下,只能有0~n-1,但我们从第0个数一直求到第n个数,我们就有了n+1个前缀,然后我们不难发现,若正好两两不同,则会多出来一个数,所以根据鸽巢原理,这个数必定属于0~n-1,也就是说这些数的前缀和在mod n意义下至少有两个是相同的,那么我们由a ≡ b (mod c) ->(a-b)%c=0,可以得出,找到两个mod n相同的前缀和的位置i ,k,那么和为n的倍数的区间即为[k+1,i],然后完了。。

代码

//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=10050;
int n;
int a[M],sum[M];
int main()
{
	while (~scanf("%d",&n))
	{
		bool flag=1;
		for (int i=1;i<=n;i++)
			scanf("%d",&a[i]),sum[i]=(sum[i-1]+a[i])%n;
		for (int i=1;i<=n&&flag;i++)
			for (int k=0;k<i&&flag;k++)
				if (sum[i]==sum[k]) 
				{
					cout<<i-k<<endl;
					for (int j=k+1;j<=i;j++)
					cout<<a[j]<<endl;
					flag=0;
				}
		if (flag) puts("0");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/80886620
今日推荐