傳送
這題的題解太妙了,雖然是dp,但從頭至尾沒一步是在我意料以內的……
一句話題意:給一個\(n\),\(q\)組詢問,每次讓求\(\sum_{i=1}^{n} C_{3i}^x \ \ \textrm{mod} \ \ 10^9+7\).(\(1 \leqslant n \leqslant 10^6, 1 \leqslant q \leqslant 2 * 10^5\))
咋dp的呢?ios
令\(dp[x][m]=\sum\limits_{i=0}^{n - 1} C_{3i+m}^x(m = 0,1,2)\).那麼\(ans[x] = dp[x][0]+C_{3n}^x\).c++
而\(\sum\limits_{m=0}^2dp[x][m]=\sum\limits_{i=0}^{n-1}(C_{3i}^x+C_{3i+1}^x+C_{3i+2}^x)=\sum\limits_{i=0}^{3n-1}C_i^x\).由於這三項相加至關於將全部\(i\in[1,3n-1]\)都訪問過了。git
接下來,根據\(\textrm{Hockey-Stick Identity}\),有\(\sum\limits_{i=0}^{3n-1}C_i^x = C_{3n}^{x+1}\).(其實這一步不知道也行,預處理出來就行了)ide
因而就有\(dp[x][0]+dp[x][1]+dp[x][2] = C_{3n}^{x+1} \ \ (1)\).ui
又根據楊輝三角,能得出關係式:
\(dp[x][1] = dp[x][0]+dp[x - 1][0] \ \ (2)\),spa
\(dp[x][2] = dp[x][1] + dp[x - 1][1] \ \ (3)\).code
最後將\((1)(2)(3)\)聯立,就能解得遞推式get
邊界條件:\(dp[0][0] = dp[0][1] = dp[0][2] = 0\).string
時間複雜度\(O(n+q)\).
太妙了。it
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<queue> #include<assert.h> #include<ctime> using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a, x) memset(a, x, sizeof(a)) #define In inline #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt) typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 3e6 + 5; const ll mod = 1e9 + 7; In ll read() { ll ans = 0; char ch = getchar(), las = ' '; while(!isdigit(ch)) las = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(las == '-') ans = -ans; return ans; } In void write(ll x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0'); } In ll ADD(ll a, ll b) {return a + b < mod ? a + b : a + b - mod;} In ll quickpow(ll a, ll b) { ll ret = 1; for(; b; b >>= 1, a = a * a % mod) if(b & 1) ret = ret * a % mod; return ret; } int n, m, Q; ll f[maxn], inv[maxn], dp[maxn][3], inv3; In ll C(int n, int m) {return f[n] * inv[m] % mod * inv[n - m] % mod;} In void init() { inv3 = quickpow(3, mod - 2); f[0] = inv[0] = 1; for(int i = 1; i <= m; ++i) f[i] = f[i - 1] * i % mod; inv[m] = quickpow(f[m], mod - 2); for(int i = m - 1; i; --i) inv[i] = inv[i + 1] * (i + 1) % mod; dp[0][0] = dp[0][1] = dp[0][2] = n; for(int i = 1; i <= m; ++i) { ll c = C(m, i + 1); dp[i][0] = ADD(ADD(c, mod - dp[i - 1][0] * 2 % mod), mod - dp[i - 1][1]) * inv3 % mod; dp[i][1] = ADD(ADD(c, dp[i - 1][0]), mod - dp[i - 1][1]) * inv3 % mod; dp[i][2] = ADD(ADD(c, dp[i - 1][0]), dp[i - 1][1] * 2 % mod) * inv3 % mod; } } int main() { n = read(), Q = read(); m = n * 3; init(); for(int i = 1; i <= Q; ++i) { int x = read(); write(ADD(dp[x][0], C(m, x))), enter; } return 0; }