CSP/NOIP新赛制内部挑战赛2 A. 二进制王国

 

 

 

sub1 (50pts)

设f[i][j] 为用前i种纸币,还需要总金额为j的方案数

枚举第i个纸币用了k 张,从f[i−1][j+k∗(2^i)] 转移


时间复杂度:O(n^2*log n)

sub2 (85pts)

其实就是无限背包的问题

直接 f[i][j]=f[i−1][j]+f[i][j+(2^i)]


第一维显然可以压缩掉
时间复杂度:O(n*log n)

 

sub3 (95pts)

面值为1 的纸币考虑完后,j 为奇数的位置就不可能转移到答案了
面值为2 的纸币考虑完后,j mod 4 != 0 的位置就不可能转移到答案了
后面的以此类推
所以转移有效位置即可

时间复杂度:O(N)

 

标算

其上一种算法的空间会炸、

观察转移的过程,可以发现程序等价于每次转移后把坐标为奇数的位置删除,然后把n/ = 2
另外容易发现,使用面值为1 的纸币时的转移相当于把数组的每个位置赋值成1
那么我们可以手动完成面值为1 的纸币的转移,时空常数均除以2

 

注意哈:面值为0也是一种方案!!

 

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e8+5;
unsigned int f[maxn];
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    f[1]=2; int n;
    scanf("%d",&n);
    if(!n)
    {
        printf("1");
        return 0;
    }
    n>>=1;    
    for(int i=2;i<=n;i++)
        f[i]=f[i-1]+f[i>>1];
    printf("%u",f[n]);
    return 0;
}

 

posted @ 2020-11-27 14:43  andyc_03  阅读(110)  评论(0编辑  收藏  举报