2015 北京区域赛 K 二叉树乱搞(数位dp 误)

来源:互联网 发布:华为查看mac表ip 编辑:程序博客网 时间:2024/05/16 14:58

题意:

f(2n) = f(n)*3 

f(2n+1) = f(n)*3+1 

mod k以后,统计异或和

n 10^18

10^18数据量,一般都要转化成二进制搞

据说还有数位dp的做法,并不会


#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>#include <queue>#include <vector>#include <iostream>#define N 520using namespace std;typedef long long ll;ll dp[6][62][70000];ll f2[62];ll nxt[6][70000][2];ll tmp[2][70000];ll ans[70000];void init(){    ll i, j, mod, t;    f2[0] = 1;    for( i = 1; i <= 60; i ++ )f2[i] = f2[i-1]*2;    for( j = 1; j <= 5; j ++ ){            if( j == 1 )mod = 3;            if( j == 2 )mod = 5;            if( j == 3 )mod = 17;            if( j == 4 )mod = 257;            if( j == 5 )mod = 65537;            for( i = 0; i < mod; i ++ ){                nxt[j][i][0] = 3*i%mod;                nxt[j][i][1] = (3*i+1)%mod;            }            dp[j][1][1] = 1;            for( i = 1; i <= 60; i ++ ){                for( t = 0; t < mod; t ++ ){                    dp[j][i+1][nxt[j][t][0]] += dp[j][i][t];                    dp[j][i+1][nxt[j][t][1]] += dp[j][i][t];                }            }// init 61 hang            for( i = 1; i <= 60; i ++ ){                for( t = 0; t < mod; t ++ ){                    dp[j][i+1][t] += dp[j][i][t];                }            }        }}int main(){    int i, j, t, p;    int T, id;    ll n, k, mod;    init();    scanf("%d", &T);    while( T -- ){        scanf("%lld%lld", &n, &k);        if( k == 3 )id = 1;        if( k == 5 )id = 2;        if( k == 17 )id = 3;        if( k == 257 )id = 4;        if( k == 65537 )id = 5;        for( i = 1; i <= 60; i ++ ){            if( n == f2[i]-1 ){                for( j = 0; j < k; j ++ ){                    ans[j] = dp[id][i][j];                }                n = 0;                break;            }            else if( n > f2[i]-1 && n < f2[i+1]-1 ){                for( j = 0; j < k; j ++ ){                    ans[j] = dp[id][i][j];                }                n -= f2[i]-1;                break;            }        }        ll res = 0;        if( !n ){            for( i = 0; i < k; i ++ ){                //printf("%lld ", ans[i]);                res ^= ans[i];            }            //puts("");            printf("%lld\n", res);            continue;        }        int fl = 1, cnt = 1, now = 1;        memset( tmp, 0, sizeof(tmp) );        tmp[1][1] = 1;        while( i > 0 ){            now ^= 1;            for( j = 0; j < k; j ++ )tmp[now][j] = 0;            for( j = 0; j < k; j ++ ){                tmp[now][nxt[id][j][0]] += tmp[now^1][j];                tmp[now][nxt[id][j][1]] += tmp[now^1][j];            }            if( n > f2[i]/2 ){                fl = nxt[id][fl][1];                n -= f2[i]/2;            }            else{                tmp[now][nxt[id][fl][1]] --;                fl = nxt[id][fl][0];            }            i --;        }        res = 0;        for( j = 0; j < k; j ++ ){            ans[j] += tmp[now][j];            //printf("%lld ",ans[j] );            res ^= ans[j];        }        //puts("");        printf("%lld\n", res);    }}


0 0