NOIP20062^k进制数
「问题描述」
(1)r至少是个2位的2k 进制数。
(2)作为2k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位。
(3)将r转换为2进制数q后,则q的总位数不超过w。
「输入文件」
「输出文件」
「输入样例」
3
「输出样例」
36
题目中的那个从另一角度分析就已经蕴含了这个题的基本思路。就以题目的例子为例,长度为7位的01字串按3位一段就这样分:0 000 000。其中除了首段,每段都小于(111)2,也即小于2k,而首段自然是小于2w%k(对于w%k为0时也成立)了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include<iostream> using namespace std; int k,n,bx,hx,ans[201]; int c[512][512][100]; void plus1(int x[],int y[],int z[]) { z[0]=max(x[0],y[0]); for(int i=1;i<=z[0];i++) { z[i]+=x[i]+y[i]; z[i+1]+=z[i]/10; z[i]%=10; } if(z[z[0]+1]!=0)z[0]++; } void plus2(int x[],int y[]) { x[0]=max(x[0],y[0]); for(int i=1;i<=x[0];i++) { x[i]+=y[i]; x[i+1]+=x[i]/10; x[i]%=10; } if(x[x[0]+1]!=0)x[0]++; } int main() { cin>>k>>n; bx=1<<k;//2^k hx=1<<(n%k); for(int i=0;i<=bx;i++) for(int j=0;j<=i;j++) { if(j==0)c[i][j][0]=c[i][j][1]=1; else plus1(c[i-1][j],c[i-1][j-1],c[i][j]); } for(int i=2;i<=n/k&&i<bx;i++)plus2(ans,c[bx-1][i]); for(int i=1;i<hx&&n/k+i<bx;i++)plus2(ans,c[bx-i-1][n/k]); for(int i=ans[0];i>=1;i--)cout<<ans[i]; cout<<endl; return 0; } |