【51nod 1103】【N的倍數】(字首和取餘)
阿新 • • 發佈:2018-11-01
題目:
一個長度為N的陣列A,從A中選出若干個數,使得這些數的和是N的倍數。
例如:N = 8,陣列A包括:2 5 6 3 18 7 11 19,可以選2 6,因為2 + 6 = 8,是8的倍數。
Input
第1行:1個數N,N為陣列的長度,同時也是要求的倍數。(2 <= N <= 50000)
第2 - N + 1行:陣列A的元素。(0 < Aii <= 10^9)
Output
如果沒有符合條件的組合,輸出No Solution。
第1行:1個數S表示你所選擇的數的數量。
第2 - S + 1行:每行1個數,對應你所選擇的數。
Sample Input
8
2
5
6
3
18
7
11
19
Sample Output
2
2
6
解題報告:字首和的取餘運算,不得不說自己剛上來是想寫dfs的,資料範圍不允許,這道題目是慣性思維了,因為上週做過的一道題目讓自己的思維卡死了,忘記了夏季學期學長出的那道題目了,本質是相同的,自己死在了思維固化了。。
其實字首和之後對N取餘,咱們只有0--N-1這N種情況,所以要麼有0存在,要麼就有相同的數字,所以不存在無解的情況。
咱們只有兩種情況需要判斷,就是1 從0-i 是取餘相同的 或者是l - r 是相同的就可以了。
ac程式碼:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int maxn=50005; int n; ll num[maxn]; ll sum[maxn]; ll pos[maxn]; int main() { while(scanf("%d",&n)!=EOF) { memset(sum,0,sizeof(sum)); memset(pos,0,sizeof(pos)); int l,r; for(int i=1;i<=n;i++) scanf("%d",&num[i]); sum[0]=0; for(int i=1;i<=n;i++) { sum[i]=(sum[i-1]+num[i])%n; if(sum[i]==0) { l=1; r=i; break; } else if(pos[sum[i]]!=0) { l=pos[sum[i]]+1; r=i; break; } pos[sum[i]]=i; } printf("%d\n",r-l+1); for(int i=l;i<=r;i++) printf("%d\n",num[i]); } }