P1066 2^k进制数
Posted five20
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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进制数r。
例:设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)。
共5+4+…+1=15个。
所以,满足要求的r共有36个。
输入输出格式
输入格式:2个正整数,用一个空格隔开:
kW
输出格式:1个正整数,为所求的计算结果,即满足条件的不同的r的个数(用十进制数表示),要求最高位不得为0,各数字之间不得插入数字以外的其他字符(例如空格、换行符、逗号等)。
(提示:作为结果的正整数可能很大,但不会超过200位)
输入输出样例
3 7
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} imes 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进制数的主要内容,如果未能解决你的问题,请参考以下文章