2^k进制数
传送
题解大佬的思路令本蒟蒻抖抖发瑟
就由本蒟蒻来讲一讲一个朴素的思路好了
通过题目解释样例可以看出来不管\(r\)的位数是多少,当前的\(r\)对答案的贡献可以用\(sum\)数组维护
为了方便,我们分成两部分来讨论
有\(\lfloor \frac{w}{k} \rfloor\)位可填的数范围是完整的\([1,2^k-1]\)(暂时不管填出来是否合法),剩余的1位的填数范围是\([1,2^{w\%k}-1\)
对于这\(\lfloor \frac{w}{k} \rfloor\) 位来说,设\(sum[i][j]\)表示从右往左数第\(i\)位,这一位当前填了\(\geq j\)的数,并且合法,对答案的贡献,当\(r\)的位数为\(i\)时,对答案的贡献就是\(sum[i][1]\)
\(sum[i][j]=\Sigma sum[i-1][l],j<l<2^k-1\)
为了省空间,可以开滚动数组
for(int i=er-1;i>=1;i--) sum[1][i]=sum[1][i+1]+1;
int n=w/k,nw,sd=er-n;
for(int i=2;i<=n&&er-i>0;i++)//确保当前枚举的位数有至少一组合法的填法
{
int b=i%2;nw=b;
sum[b][er-i]=sum[b^1][er-i+1];
for(int j=er-i-1;j>=1;j--) sum[b][j]=sum[b][j+1]+sum[b^1][j+1];
ans=ans+sum[b][1];
}
然后再来个高精就可以了
完整代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
char ch=getchar();
int x=0;bool f=0;
while(ch<'0'||ch>'9')
{
if(ch=='-') f=1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return f?-x:x;
}
int k,w;
struct gj
{
int a[209],len;
}sum[2][519],ans;
gj operator +(gj a,gj qaq)
{
gj rtn;
int mx=max(qaq.len,a.len),x=0;
if(a.len<mx) for(int i=a.len+1;i<=mx;i++) a.a[i]=0;
if(qaq.len<mx) for(int i=qaq.len+1;i<=mx;i++) qaq.a[i]=0;
rtn.len=mx;
for(int i=1;i<=mx;i++)
{
rtn.a[i]=qaq.a[i]+a.a[i]+x;
x=rtn.a[i]/10;
rtn.a[i]%=10;
}
if(x) rtn.a[mx+1]=x,rtn.len++;
return rtn;
}
gj operator+(gj a,int b)
{
gj qaq;
int qwq=b,l=0;
while(qwq)
{
qaq.a[++l]=qwq%10;
qwq/=10;
}
qaq.len=l;
return a+qaq;
}
void print(gj a)
{
for(int i=a.len;i>=1;i--)
printf("%d",a.a[i]);
printf("\n");
}
int main()
{
k=read();w=read();int er=1;
for(int i=1;i<=k;i++) er*=2;
for(int i=er-1;i>=1;i--) sum[1][i]=sum[1][i+1]+1;
int n=w/k,nw,sd=er-n;
for(int i=2;i<=n&&er-i>0;i++)
{
int b=i%2;nw=b;
sum[b][er-i]=sum[b^1][er-i+1];
for(int j=er-i-1;j>=1;j--) sum[b][j]=sum[b][j+1]+sum[b^1][j+1];
ans=ans+sum[b][1];
}
n=w%k;
if(!n){print(ans);return 0;}
er=1;
for(int i=1;i<=n;i++) er*=2;
for(int i=1;i<=er-1&&i<sd;i++) ans=ans+sum[nw][i+1];
print(ans);
}