一個密鑰是一個長度爲 n=2k+1n=2k+1 的字符串,它包含 11 個字母X、kk 個字母 A 和 kk 個字母 B。例如 k=3k=3 時,BAXABAB 就是一個密鑰。ios
以下圖所示,能夠按順時針順序把這 2k+12k+1 個字母排成一個圈:數組
在 kk 個字母 A 中,有一部分能夠定義爲"強的"。ide
具體來講,從 X 出發順時針走到某個 A 時,若是途中 A 的數目嚴格多於 B 的數目,則稱此字母 A 爲強的。測試
對於上面的例子來講,順時針方向從字母 X 數起第 11 個和第 22 個字母 A 是強的,而第 33 個字母 A 不是強的。atom
一個密鑰的特徵值就是其中包含的強的字母 A 的個數。spa
天才小朋友 KT 給出了一個結論:code
假設 kk 個字母 A 所在的位置已經固定,可是剩下的 kk 個 B 和 11 個 X 的位置是未知的。 (注意,知足這樣要求的密鑰一共有 k+1k+1 個,由於字母 X 還剩下 k+1k+1 個可能的位置。)orm
能夠證實:全部這k+1k+1個可能的密鑰的特徵值是各不相同的,它們剛好爲0,1,2,…,k0,1,2,…,k。xml
下頁的圖是一個具體的示例,從左到右的四個子圖中分別有3個,2個,1個,0個字母A是強的。blog
相似地,若是固定 kk 個字母 B 的位置,那知足條件的全部 k+1k+1 個密鑰的特徵值也各不相同,剛好爲 0,1,⋯,k0,1,⋯,k。
如今你須要解決如下三個問題:
注意:字符串的 2k+12k+1 個字母的位置由 11 到 2k+12k+1 編號。
假定 k=3,Sk=3,S=2。那麼:
當 A 的位置是 {2,4,6}{2,4,6} 且特徵值爲 00 時,X 的位置在 77;
當 A 的位置是 {2,4,6}{2,4,6} 且特徵值爲 22 時,X 的位置在 33;
當 B 的位置是 {2,4,6}{2,4,6} 且特徵值爲 22 時,X 的位置在 55。
假定 k=9,Sk=9,S=7。那麼:
當 A 的位置是 {3,4,5,9,10,12,13,16,19}{3,4,5,9,10,12,13,16,19} 且特徵值爲 00 時,X 的位置在 1414;
當 A 的位置是 {3,4,5,9,10,12,13,16,19}{3,4,5,9,10,12,13,16,19} 且特徵值爲 77 時,X 的位置在 1818;
當 B 的位置是 {3,4,5,9,10,12,13,16,19}{3,4,5,9,10,12,13,16,19} 且特徵值爲 77 時,X 的位置在 1717。
只包含一組測試數據。
第一行包含一個整數kk,意義如題所述。
第二行包含一個整數seedseed,這個數將用於生成一個kk元集合P。
第三行包含一個整數SS,意義如題所述。
保證0≤S0≤S≤k≤107。1≤seed1≤seed≤10000。
在下發文件中,包含三個用於生成輸入數據的文件cipher.cpp/c/pas
。其中讀入部分已經完成,在數組 p[]p[] 中,若 p[i]=0p[i]=0,表示 ii 不屬於集合PP,不然,ii 屬於集合 PP。
輸出三行,每行一個數,依次對應問題描述中的三個子問題的答案。
即:
5 3344 2
10 1 2
第一個樣例中,PP 數組爲 11 的元素的下標分別爲 5,6,7,8,95,6,7,8,9。
500000 4545 234567
999992 246922 753067
對於 30%30% 的數據,k≤103k≤103。
對於 50%50% 的數據,k≤105k≤105。
對於 100%100% 的數據,k≤107k≤107。
對於每一個測試點,得分爲如下三部分得分之和:
若是你僅僅知道部分答案,請也務必按此格式要求輸出三個數。不然你可能會因格式錯誤沒法得分。
時間限制:1s1s
空間限制:512MB
#include<iostream> #include<cstdio> #include<cstring> #define maxn 20000005 using namespace std; int p[maxn],b[maxn],cnt,ans[maxn]; int seed, n, k, S; int getrand() { seed = ((seed * 12321) ^ 9999) % 32768; return seed; } void generateData() { scanf("%d%d%d",&k,&seed,&S); int t = 0; n = k * 2 + 1; memset(p, 0, sizeof(p)); for (int i = 1; i <= n; i++) { p[i] = (getrand() / 128) % 2; t += p[i]; } int i = 1; while (t > k) { while (p[i] == 0) i++; p[i] = 0; t--; } while (t < k) { while (p[i] == 1) i++; p[i] = 1; t++; } } int count1(int s){ int sa=0,sb=0,res=0; for(int i=2,j=s+1;i<=n;i++,j++){ if(p[j]==0)sb++; else { sa++; if(sa>sb)res++; } } return res; } void work1(){ for(int i=1;i<=cnt;i++)//x的位置 ans[i]=count1(b[i]); } int count2(int s){ int sa=0,sb=0,res=0; for(int i=2,j=s+1;i<=n;i++,j++){ if(p[j]==1)sb++; else { sa++; if(sa>sb)res++; } } return res; } void work2(){ for(int i=1;i<=cnt;i++) ans[i]=count2(b[i]); } int main(){ generateData(); for(int i=1;i<=n;i++)p[i-1]=p[i]; for(int i=0;i<n;i++)p[i+n]=p[i]; for(int i=0;i<n;i++)if(!p[i])b[++cnt]=i; if(k<=1000){ work1(); int ans0,ans1; for(int i=1;i<=cnt;i++){ if(ans[i]==0)ans0=b[i]+1; if(ans[i]==S)ans1=b[i]+1; } printf("%d\n%d\n",ans0,ans1); work2(); for(int i=1;i<=cnt;i++) if(ans[i]==S){ printf("%d\n",b[i]+1); return 0; } } return 0; }