【Ural】【1057】Amount of degrees

数位DP



2009年刘聪《浅谈数位类统计问题》 例题一

从组合数 以及 数位DP的角度都可以做……

首先转化成求1~n内K进制下只有0、1的数的个数:

  考虑K进制下第一个为1的位,剩下的数位中0和1随便放……也就是算组合数了。

  然后区间相减……

写的好乱……还是去看论文吧

 1 //Ural 1057
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<iostream>
 6 #include<algorithm>
 7 #define rep(i,n) for(int i=0;i<n;++i)
 8 #define F(i,j,n) for(int i=j;i<=n;++i)
 9 #define D(i,j,n) for(int i=j;i>=n;--i)
10 using namespace std;
11 
12 int getint(){
13     int v=0,r=1; char ch=getchar();
14     for(;ch<'0' || ch>'9';ch=getchar()) if (ch=='-') r=-1;
15     for(;ch>='0'&&ch<='9';ch=getchar()) v=v*10+ch-'0';
16     return v*r;
17 }
18 /*******************template********************/
19 int f[40][40];
20 void init(){
21     f[0][0]=1;
22     F(i,1,31){
23         f[i][0]=f[i-1][0];
24         F(j,1,i) f[i][j]=f[i-1][j]+f[i-1][j-1];
25     }
26 }
27 int calc(int x,int k){
28     int tot=0,ans=0;
29     D(i,31,1){
30         if (x&(1<<i)){
31             ++tot;
32             if(tot>k)break;
33             x=x^(1<<i);
34         }
35         if ( (1<<(i-1))<=x )
36             ans+=f[i-1][k-tot];
37     }
38     if (tot+x==k) ++ans;
39     return ans;
40 }
41 int a[40];
42 int change(int x,int b){
43     int l=0;
44     for(l=0;x;l++,x/=b) a[l]=x%b;
45     D(i,l-1,0) if (a[i]>1){
46         D(j,i,0) a[j]=1;
47         break;
48     }
49     int temp=0;
50     D(i,l-1,0) temp=(temp<<1)+a[i];
51     return temp;
52 }
53 int main(){
54 //    freopen("input.txt","r",stdin);
55     init();
56     int l=getint(),r=getint(),k=getint(),b=getint();
57     int ans=0;
58     if (b!=2) ans=calc(change(r,b),k)-calc(change(l-1,b),k);
59     else ans=calc(r,k)-calc(l-1,k);
60     printf("%d
",ans); 
61     return 0;
62 }
View Code
原文地址:https://www.cnblogs.com/Tunix/p/4306762.html