[NOIP2006]2^k进制数

做题时间:2021.02.03

问有多少个2k(k9)进制数满足:

  1. 至少有2位;
  2. 转化为2进制数之后最多有w位。
  3. 除最后一位外,每一位都严格小于右边一位

3 7

36

动态规划 or 组合数学、高精度


#include<cstdio>
#include<iomanip>
#include<iostream>
#include<cstring>
using namespace std;
const int N=205;
const int M=1<<9;
string C[M][M],p,t,ans;
int a[N],b[N],c[N];
int w,k;
inline int Swap(int &x,int &y){int t=x;x=y;y=t;}
string Add(string sa,string sb)//高精度加法
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(b,0,sizeof(c));
t="";
int lena=sa.size();
int lenb=sb.size(),lenc;
for(int i=0;i<lena;i++) a[i+1]=sa[lena-i-1]-'0';
for(int i=0;i<lenb;i++) b[i+1]=sb[lenb-i-1]-'0';
int i=1,x=0;
while(i<=lena||i<=lenb){
c[i]=a[i]+b[i]+x;
x=c[i]/10;
c[i]%=10;
i++;
}
if(x) c[i]=x;
else i--;
lenc=i;
for(int i=lenc;i>=1;i--) t+=(char)c[i]+'0';
return t;
}
int main()
{
scanf("%d%d",&k,&w);
int ed=1<<k,sp=1<<w%k;
C[0][0]="1";
for(int i=1;i<=ed;i++) C[i][0]=C[i][i]="1";
for(int i=2;i<=ed;i++){
for(int j=1;j<i;j++) C[i][j]=Add(C[i-1][j],C[i-1][j-1]);//预处理组合数
}
//这里其实可以将k整除w和k不整除w两种情况写在一起
for(int i=2;i<=w/k;i++){
if(i>ed-1) break;
ans=Add(ans,C[ed-1][i]);//累加
}
for(int i=1;i<=sp-1;i++){
if(w/k>ed-i-1) break;
ans=Add(ans,C[ed-i-1][w/k]);//累加
}
int len=ans.size();
for(int i=0;i<len;i++) printf("%c",ans[i]);
return 0;
}

本文作者:lxzy

本文链接:https://www.cnblogs.com/Unlimited-Chan/p/14368051.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   lxzy  阅读(98)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.