本文主要是介绍poj3370nbsp;poj2356nbsp;鸽巢定理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
解梯报告
题目链接 :http://poj.org/problem?id=3370
题目大意 :给你n个数,找出其中c个数满足c个数的和是c的倍数。(c <=n)
思路 :余数计算 + 鸽巢定理。
取余是一种常用手段,尤其是当题目中找一些数字直接和的关系的时候,往往通过
余数来将数字分类。2011年多校FZU有一位dp的题目就可以用余数乱搞。
将前i个数的和模c的值存下来,如果sum[i] = 0或sum[i]之前第k位出现过,那么
Sum[i] – sum[k] = 0,即k+1到i是满足模c余零的。到这里还没有用到鸽巢定理,题
目描述里有无解的情况,而一个重要的信息(c<=n)告诉我们这里是必然有解的。
余数有c个(0到c)要放到n个盒子里(n>=c)那么必然有一个是0或者有两个是
一样的。《鸽巢定理》
AC code:
#include <cstdio>
#include <cstring>
#define MAXN 100100
int num[MAXN], sum[MAXN], vis[MAXN];
void print(int a, int b){
for(int i = a; i <= b; ++ i) printf("%d ", i);
printf("\n");
}
int main(){
int c, n;
while(~scanf("%d %d", &c, &n), c || n){
for(int i = 1; i <= n; i ++){
scanf("%d", &num[i]);
}
memset(vis, 0, sizeof(vis));
sum[0] = 0;
for(int i = 1; i <= n; ++ i){
sum[i] = (sum[i - 1] + num[i]) % c;
if(sum[i] == 0){
print(1, i);
break;
}
if(vis[sum[i]]){
print(vis[sum[i]] + 1, i);
break;
}
vis[sum[i]] = i;
}
}
return 0;
}
这篇关于poj3370nbsp;poj2356nbsp;鸽巢定理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!