• 2^k进制数


    传送
    题解大佬的思路令本蒟蒻抖抖发瑟
    就由本蒟蒻来讲一讲一个朴素的思路好了
    通过题目解释样例可以看出来不管(r)的位数是多少,当前的(r)对答案的贡献可以用(sum)数组维护
    为了方便,我们分成两部分来讨论
    (lfloor frac{w}{k} floor)位可填的数范围是完整的([1,2^k-1])(暂时不管填出来是否合法),剩余的1位的填数范围是([1,2^{w\%k}-1)
    对于这(lfloor frac{w}{k} floor) 位来说,设(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("
    "); 
    }
    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);
    }
    
  • 相关阅读:
    简易模拟点击自动化测试工具介绍
    HttpRunner 使用简介
    postman生成测试报告
    Java 多态
    Java 接口与接口的多继承关系
    Java 类实现接口
    Java 接口内容小结
    Java 接口
    Java 抽象
    Java 继承
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/13081058.html
Copyright © 2020-2023  润新知