hihocoder 1259 (数位DP)

来源:互联网 发布:java字符串截取前几位 编辑:程序博客网 时间:2024/05/28 17:07

连接:点击打开链接

题意:定义g(x)为f(1)到f(n)中模k余n的个数,求出所有g(x)的异或和.

坑爹UVA一直报RE然后转向hihocoder就过了~

f(2x)=3f(x),f(2x+1)=f(2x)+1.

然后发现f(1)到f(n)在三进制下等价于二进制下的1到n,然后就可以用数位DP搞了.

这个思想下的转移方程dp(d,m) = dp(d-1, (m-x)%k).

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>using namespace std;long long dp[68][68686];long long n, ans[68686];int mod;int bit[68], l;#define pow Powlong long pow[68];void solve (long long num) {    long long cur = 1;    l = 0;    while (num) {        bit[++l] = (num&1);        num >>= 1;    }    pow[0] = 1;    for (int i = 1; i <= l; i++) pow[i] = pow[i-1]*3%mod;    for (int i = 1; i <= l; i++, cur *= 3, cur %= mod) {        for (int j = 0; j < mod; j++) {            dp[i][(j+cur)%mod] += dp[i-1][j];//1            dp[i][j] += dp[i-1][j];//0        }    }    memset (ans, 0, sizeof ans);    cur = 0;    for (int i = l; i >= 1; i--) {        if (bit[i]) {            for (int j = 0; j < mod; j++) {                ans[(j+cur)%mod] += dp[i-1][j];            }            cur += pow[i-1]%mod;            cur %= mod;        }    }    ans[cur]++;//最终的数字    ans[0]--;//排除数字0    long long gg = 0;    for (int i = 0; i < mod; i++) {        gg ^= ans[i];    }     cout << gg << endl;    return ;}int main () {    //freopen ("in.txt", "r", stdin);    int t;    scanf ("%d", &t);    while (t--) {        memset (dp, 0, sizeof dp);        dp[0][0] = 1;        scanf ("%lld%d", &n, &mod);        solve (n);    }    return 0;}


0 0