POJ 2356:
题目大意:
给定n个数,希望在这n个数中找到一些数的和是n的倍数,输出任意一种数的序列,找不到则输出0
这里首先要确定这道题的解是必然存在的
利用一个 sum[i]保存前 i 个数的和对n的取模
sum[0] = 0;
那么sum[0] ~ sum[n]有n+1个数据,这些数据的范围都是 0~n , 要是存在 sum[i] = 0,那么输出前 i 个数据即可
要是不存在那根据鸽巢原理可以说明必然能找到一个 sum[i] = sum[j] ,那么说明 (sum[i+1] + sum[i+2] ...+sum[j])%n = 0的,把这j-i个数输出即可
那么说明我们总是能找到一段连续的数据使其和是n的倍数
1 #include <cstdio> 2 #include <cstring> 3 4 using namespace std; 5 const int N = 10005; 6 7 bool vis[N]; 8 int sum[N] , a[N] , pos[N]; 9 10 int main() 11 { 12 // freopen("a.in" , "r" , stdin); 13 int n; 14 while(scanf("%d" , &n) != EOF) 15 { 16 for(int i=1 ; i<=n ; i++){ 17 scanf("%d" , a+i); 18 } 19 memset(vis , 0 , sizeof(vis)); 20 vis[0] = 1 , pos[0] = 0; 21 for(int i=1 ; i<=n ; i++){ 22 sum[i] = (sum[i-1]+a[i])%n; 23 if(vis[sum[i]]){ 24 int l = pos[sum[i]]; 25 printf("%d\n" , i-l); 26 for(int j = l+1 ; j<=i ; j++){ 27 printf("%d\n" , a[j]); 28 } 29 break; 30 } 31 pos[sum[i]] = i; 32 vis[sum[i]] = 1; 33 } 34 } 35 return 0; 36 }
POJ3370:
1 #include <cstdio> 2 #include <cstring> 3 4 using namespace std; 5 #define N 100005 6 bool vis[N]; 7 int sum[N] , a[N] , pos[N]; 8 9 int main() 10 { 11 // freopen("a.in" , "r" , stdin); 12 int c , n; 13 while(scanf("%d%d" , &c , &n) , c||n) 14 { 15 for(int i=1 ; i<=n ; i++) 16 scanf("%d" , a+i); 17 memset(vis , 0 ,sizeof(vis)); 18 sum[0] = 0 , vis[0] = 1 , pos[0] = 0; 19 for(int i=1 ; i<=n ; i++){ 20 sum[i] = (sum[i-1] + a[i])%c; 21 if(vis[sum[i]]){ 22 int l = pos[sum[i]]; 23 for(int j=l+1 ; j<=i ; j++){ 24 if(j == l+1) printf("%d" , j); 25 else printf(" %d" , j); 26 } 27 printf("\n"); 28 break; 29 } 30 vis[sum[i]] = 1; 31 pos[sum[i]] = i; 32 } 33 } 34 return 0; 35 }
我还在坚持,我还未达到我所想,梦~~一直在