2018.6.6 T4数学游戏

Pro4 数学游戏 (maga.pas/cpp/c)
题目描述:

小T又发脑残了,没错,她又要求奇怪的东西,这次她想知道[X,Y]之间整数有多少可以表示成K个不同的B的幂的和形势。如x,y,k,b=15,20,2,2,则有:
17=2^4+2^0
18=2^4+2^1
20=2^4+2^2 共3个符合要求的数

输入格式:

输入仅包含一行4个空格隔开的整数X,Y,K,B(1≤X≤Y≤2^31 -1,1≤K≤20)

输出格式:

输出文件包含一行一个即为所求合法数字个数。

样例输入:

15 20 2 2

样例输出:

3


这题题面本来是 k <= 10
因此dfs k ! 就可以轻松过
然而暴力只有78%
幂次数使我们想到进制,问题就转化成了B进制下求位上总和为k的数
这显然可以用数位dp做
f [ i ] [ j ] [ k ] 表示前i位,是否满,位和为k时的方案数,因为必须不同,所以每位只要枚举1和0
然后是模板
最后B=1要特判

//我比较喜欢用记搜
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int x,y,k,b;
int a[50],f[50][2][25];
int dfs(int ln,int p,int sum) {
    if (sum>k) return 0;
    if (ln==0) {
        if (sum==k) return 1;
        else return 0;
    }
    if (!p && f[ln][p][sum]!=-1) return f[ln][p][sum];
    int cnt=0;
    for (int i=0;i<=1;i++) {
        if (p && i>a[ln]) continue;
        int p1=p;
        if (i<a[ln]) p1=0;
        cnt+=dfs(ln-1,p1,sum+i);
    }
    if (!p) f[ln][p][sum]=cnt;
    return cnt; 
}
int chu(int x) {
    memset(f,-1,sizeof f);
    int cnt=0;
    while (x) {
        a[++cnt]=x%b;
        x/=b;
    }
    return dfs(cnt,1,0);
}
int main() {
    freopen("maga.in","r",stdin);
    freopen("maga.out","w",stdout);
    scanf("%d%d%d%d",&x,&y,&k,&b);
    if (b==1) {
        if (x<=1 && k==1) puts("1");
        else puts("0");
        return 0;
    }
    printf("%d\n",chu(y)-chu(x-1));
}

猜你喜欢

转载自blog.csdn.net/qq_41893580/article/details/80596806
T4
今日推荐