团不过(dp)
團不過
- problem
- solution
- code
problem
由比濱結衣和雪之下雪乃在玩 NimNimNim 游戲。
共有 nnn 堆石子,雙方輪流操作,每次可以從一堆非空石子堆中取走任意個石
子,取走最后一個石子的人勝利。
她們決定讓由比濱結衣先手,但忘記了每堆初始時含有石子的數目,只知道
每堆至少有 111 個石子,但數目小于 2n2^n2n ,且每堆石子的數目互不相同。
一共有多少種可能的情況使得由比濱結衣能夠取勝呢?
兩種情況不同當且僅當存在一堆石子在兩種情況中含有的石子數目不同。
由于答案可能很大,你只需要輸出答案對 109+710^9 + 7109+7 取模的結果。
友情提示:在 NimNimNim 游戲中,先手必勝等價于各堆石子數目異或之和不為 000 。
n≤1e7n\le 1e7n≤1e7。
solution
正睿原題我是nm沒想到,還有人寫過題解,草!我已經跟他們隔了一層可悲的厚障壁了!qwq
考慮在限定每堆石子個數互不相同的情況下,用總方案數減去先手必敗的方案數。
設 pi:ip_i:ipi?:i 堆石子的方案數,即 ∑k=1i(2n?1?k+1)\sum_{k=1}^i(2^n-1-k+1)∑k=1i?(2n?1?k+1)。
設 fi:if_i:ifi?:i 堆石子的游戲下,先手必敗的方案數。
考慮 fif_ifi? 的轉移。
- 如果前 i?1i-1i?1 堆石子異或和為 000 ,則第 iii 堆石子只能是 000,但這不合法,所以要減掉 fi?1f_{i-1}fi?1?。
- 如果其中有 i?2i-2i?2 堆石子異或和為 000,則第 iii 堆石子必須和剩下的一堆石子相同,也不合法,所以要減去 fi?2?(i?11)?(2n?1?(i?2))f_{i-2}·\binom{i-1}{1}·(2^n-1-(i-2))fi?2??(1i?1?)?(2n?1?(i?2))【(i?11)\binom{i-1}{1}(1i?1?)枚舉除了哪堆石子外其余石子異或和為 000,(2n?1?(i?2))(2^n-1-(i-2))(2n?1?(i?2))減去 i?2i-2i?2 堆互不相同的石子數,剩下的可選數目即為第 iii 堆石子和剩下一堆石子的數量。】
即 fi=pi?1?fi?1?fi?2?(i?1)?(2n?i+1)f_i=p_{i-1}-f_{i-1}-f_{i-2}·(i-1)·(2^n-i+1)fi?=pi?1??fi?1??fi?2??(i?1)?(2n?i+1)。
邊界情況 f1=f2=0f_1=f_2=0f1?=f2?=0。
時間復雜度 O(n)O(n)O(n)。
code
#include <cstdio> #define int long long #define maxn 10000005 #define mod 1000000007 int n, x, cnt; int Pow[maxn], f[maxn];int qkpow( int x, int y ) {int ans = 1;while ( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans; }signed main() {freopen( "yui.in", "r", stdin );freopen( "yui.out", "w", stdout );scanf( "%lld", &n );Pow[0] = 1; cnt = x = qkpow( 2, n ) - 1;for( int i = 1;i <= n;i ++ ) Pow[i] = Pow[i - 1] * cnt % mod, cnt --;f[1] = f[2] = 0;for( int i = 3;i <= n;i ++ ) f[i] = ( Pow[i - 1] - f[i - 1] - ( i - 1 ) * ( x - i + 2 ) % mod * f[i - 2] % mod ) % mod;printf( "%lld\n", ( ( Pow[n] - f[n] ) % mod + mod ) % mod );return 0; }總結
- 上一篇: 尽梨了(贪心+dp)
- 下一篇: 12.4 寸 1759 元大促:小米平板