Codeforces Round #167 (Div. 1) E. Dima and Game

 

一个 $(l,r)$ 有两个后继,所以 sg 值最大只有 2,$r-l+1$ 相等的 pair 的 sg 值相同,那么就枚举 $d=r -l+1$,对于一个 $d$ 很容易求有多少对 $(l,r)$ 满足 $r-l+1=d$

打表发现 $d$ 的 sg 值最多只有 100 段。

设 $g_i$ 表示有多少对 $(l,r)$ sg 值为 $i$,把表打出来之后就很容易求出 $g$ 数组

那么就可以 dp 了。

$dp[i][j]$ 表示选完前 $i$ 组之后当前 sg 异或值为 $j$

$dp[i][j\oplus k]=\sum dp[i-1][j]*g[k]$,$\oplus$ 表示异或

Codeforces Round #167 (Div. 1) E. Dima and Game
#include <bits/stdc++.h>

const int MOD = 1e9 + 7;
const int N = 1007;
int pos[110] = {1,3,4,5,7,9,13,15,19,27,39,40,57,58,81,85,120,121,174,179,255,260,363,382,537,544,780,805,1146,1169,1632,1718,2415,2447,3507,3622,5154,5260,7341,7730,10866,11011,15780,16298,23190,23669,33033,34784,48894,49549,71007,73340,104352,106510,148647,156527,220020,222970,319530,330029,469581,479294,668910,704371,990087,1003364,1437882,1485130,2113113,2156822,3010092,3169669,4455390,4515137,6470466,6683084,9509007,9705698,13545411,14263510,20049252,20318116,29117094,30073877,42790530,43675640,60954348,64185794,90221631,91431521,131026920,135332446,192557382,196540379,274294563,288836072,405997338,411441844,589621137,608996006,866508216,884431705,1000000001};
int sg[110] = {0,1,2,1,2,0,1,2,0,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1,2,0,2,1};
int g[3], dp[N][4], n, p;

void M(int &a) {
    if (a >= MOD) a -= MOD;
    if (a < 0) a += MOD;
}

int cal(int l, int r) {
    l = p - l, r = p - r;
    return 1LL * (l + r) * (l - r + 1) / 2 % MOD;
}

int main() {
    scanf("%d%d", &n, &p);
    for (int i = 0; i < 102; i++) {
        if (pos[i] > p) break;
        int l = pos[i], r = std::min(pos[i + 1] - 1, p);
        M(g[sg[i]] += cal(l, r));
    }
    dp[0][0] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < 4; j++) {
            for (int k = 0; k <= 2; k++) {
                M(dp[i][j ^ k] += 1LL * dp[i - 1][j] * g[k] % MOD);
            }
        }
    }
    int ans = 0;
    for (int i = 1; i < 4; i++)
        M(ans += dp[n][i]);
    printf("%d\n", ans);
    return 0;
}
View Code

 

上一篇:C++笔试题模版汇总(四)


下一篇:博弈论