P1066 2^k進制數
題目描述
設r是個2k 進制數,並滿足以下條件:
(1)r至少是個2位的2k 進制數。
(2)作為2k 進制數,除最後一位外,r的每一位嚴格小於它右邊相鄰的那一位。
(3)將r轉換為2進制數q後,則q的總位數不超過w。
在這裏,正整數k(1≤k≤9)和w(k<W≤30000)是事先給定的。
問:滿足上述條件的不同的r共有多少個?
我們再從另一角度作些解釋:設S是長度為w 的01字符串(即字符串S由w個“0”或“1”組成),S對應於上述條件(3)中的q。將S從右起劃分為若幹個長度為k的段,每段對應一位2k進制的數,如果S至少可分成2段,則S所對應的二進制數又可以轉換為上述的2k
例:設k=3,w=7。則r是個八進制數(23=8)。由於w=7,長度為7的01字符串按3位一段分,可分為3段(即1,3,3,左邊第一段只有一個二進制位),則滿足條件的八進制數有:
2位數:
高位為1:6個(即12,13,14,15,16,17),
高位為2:5個,
…,
高位為6:1個(即67)。
共6+5+…+1=216+5+…+1=216+5+…+1=21個。
3位數:
高位只能是1,
第2位為2:5個(即123,124,125,126,127),
第2位為3:4個,
…,
第2位為6:1個(即167)。
所以,滿足要求的r共有36個。
輸入輸出格式
輸入格式:2個正整數,用一個空格隔開:
kW
輸出格式:1個正整數,為所求的計算結果,即滿足條件的不同的r的個數(用十進制數表示),要求最高位不得為0,各數字之間不得插入數字以外的其他字符(例如空格、換行符、逗號等)。
(提示:作為結果的正整數可能很大,但不會超過200位)
輸入輸出樣例
輸入樣例#1:3 7
輸出樣例#1:
36
說明
NOIP 2006 提高組 第四題
Solution:
本題DP+高精。
DP比較明顯,定義狀態$f[i][j]$表示第$i$位為$j$的方案數,則$f[i][j]=\sum f[i-1][k],k<j$。
首先第一維是可以滾掉的,然後轉移時不需要枚舉$k$,我們直接改下狀態$f[i][j]$表示第$i$位$\leq j$的方案數,每次轉移時改為維護前綴和,就能做到$O(w)$轉移($\frac{w}{k}\times k=w$)。
那麽再在DP的基礎上寫個高精就好了。
代碼:
/*Code by 520 -- 9.14*/ #include<bits/stdc++.h> #define il inline #define ll long long #define RE register #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--) using namespace std; const int N=55,Base=1e5; int n,m; struct node{ int a[N],len; il void Clr(){memset(a,0,sizeof a),len=0;} il void Push(int x){a[len=1]=1;} node operator + (const node &x) const{ node tp;tp.Clr();tp.len=max(len,x.len)+5; For(i,1,tp.len) tp.a[i]+=a[i]+x.a[i], tp.a[i+1]+=tp.a[i]/Base, tp.a[i]%=Base; For(i,1,tp.len) tp.a[i+1]+=tp.a[i]/Base,tp.a[i]%=Base; while(tp.len&&!tp.a[tp.len]) tp.len--; return tp; } il void Output(){ printf("%d",a[len]); Bor(i,1,len-1) printf("%05d",a[i]); } }ans,f[2][520]; int main(){ cin>>n>>m; int pos=m/n,rest=m%n; int minn=(1<<rest)-1,maxn=(1<<n)-1; if(!rest) minn=maxn,pos--; Bor(i,1,maxn) f[0][i].Push(1); Bor(i,1,maxn) f[0][i]=f[0][i]+f[0][i+1]; int tag=0; For(i,1,pos-1){ Bor(j,1,maxn) f[tag^1][j]=f[tag^1][j]+f[tag^1][j+1]+f[tag][j+1],f[tag][j+1].Clr(); f[tag][1].Clr(); tag^=1,ans=ans+f[tag][1]; } Bor(j,1,minn) f[tag^1][j]=f[tag^1][j]+f[tag^1][j+1]+f[tag][j+1]; ans=ans+f[tag^1][1]; ans.Output(); return 0; }
P1066 2^k進制數