2015 北京區域賽 K 二叉樹亂搞(數位dp 誤)

題意:

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 520
using 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);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章