2018ACM-ICPC徐州賽區網路賽: A. Hard to prepare【遞推】
阿新 • • 發佈:2018-12-09
題目連結:傳送門
題意就不說了
思路:
一開始比賽的時候就是想
k = 2^m
答案等於 k*((k-1)^(m-1)) 發現多了情況 因為是個環
然後換成 k*((k-2)^(m-1))*(k-2) 發現漏算了第一個和倒數第二個相同的情況
看了網上的其他題解,包括比賽時打的表明白了這其中的規律
那麼我們可以先算出第一個和倒數第二個不同的情況,而當他們相同的時候那麼最後一個就有(k-1)種情況,那麼就相當於整個長度被減去了2,得出的結果再加上去,可以由此進行dfs,因為給的n的值不大,時間複雜度是O(n),最後得出結果。
#include<bits/stdc++.h> #define ll long long #define MOD 1000000007 #define MAXN 1000005 using namespace std; ll inv[MAXN]; ll k, n, m; void init() { inv[1] = 2; for(int i = 2; i < MAXN; i++){ inv[i] = inv[i-1] * 2LL % MOD; } } ll qpow(ll a, ll b){ ll t = a, ans = 1; while(b) { if(b % 2){ ans = ans * t % MOD; } t = t * t % MOD; b /= 2; } return ans; } ll cheak(ll len){ if(len == 1){ return k; } if(len == 2){ return k * (k - 1) % MOD; } ll res = 0; res = k * qpow(k - 1, len - 2) % MOD * (k - 2) % MOD + cheak(len - 2) % MOD; return res; } int main() { int t; scanf("%d", &t); init(); while(t--) { scanf("%lld%lld", &n, &m); k = inv[m] % MOD; printf("%lld\n", cheak(n) % MOD); } return 0; }