zoukankan      html  css  js  c++  java
  • CF1548C The Three Little Pigs

    传送


    这题的题解太妙了,虽然是dp,但从头到尾没一步是在我意料之内的……


    一句话题意:给一个(n)(q)组询问,每次让求(sum_{i=1}^{n} C_{3i}^x extrm{mod} 10^9+7).((1 leqslant n leqslant 10^6, 1 leqslant q leqslant 2 * 10^5)


    咋dp的呢?

    (dp[x][m]=sumlimits_{i=0}^{n - 1} C_{3i+m}^x(m = 0,1,2)).那么(ans[x] = dp[x][0]+C_{3n}^x).

    (sumlimits_{m=0}^2dp[x][m]=sumlimits_{i=0}^{n-1}(C_{3i}^x+C_{3i+1}^x+C_{3i+2}^x)=sumlimits_{i=0}^{3n-1}C_i^x).因为这三项相加相当于将所有(iin[1,3n-1])都访问过了。

    接下来,根据( extrm{Hockey-Stick Identity}),有(sumlimits_{i=0}^{3n-1}C_i^x = C_{3n}^{x+1}).(其实这一步不知道也行,预处理出来就好了)

    于是就有(dp[x][0]+dp[x][1]+dp[x][2] = C_{3n}^{x+1} (1)).

    又根据杨辉三角,能得出关系式:
    (dp[x][1] = dp[x][0]+dp[x - 1][0] (2))

    (dp[x][2] = dp[x][1] + dp[x - 1][1] (3)).

    最后将((1)(2)(3))联立,就能解得递推式

    [egin{align*} dp[x][0] &= frac1{3}(C_{3n}^{x+1} - 2dp[x-1][0] - dp[x - 1][1]) \ dp[x][1] &= frac1{3}(C_{3n}^{x+1} + dp[x-1][0] - dp[x - 1][1]) \ dp[x][2] &= frac1{3}(C_{3n}^{x+1} + dp[x-1][0] + 2dp[x - 1][1]) end{align*}]

    边界条件:(dp[0][0] = dp[0][1] = dp[0][2] = 0).

    时间复杂度(O(n+q)).


    太妙了。

    #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;
    }
    
  • 相关阅读:
    第三天 moyax
    mkfs.ext3 option
    write file to stroage trigger kernel warning
    download fomat install rootfs script
    custom usb-seriel udev relus for compatible usb-seriel devices using kermit
    Wifi Troughput Test using iperf
    learning uboot switch to standby system using button
    learning uboot support web http function in qca4531 cpu
    learngin uboot design parameter recovery mechanism
    learning uboot auto switch to stanbdy system in qca4531 cpu
  • 原文地址:https://www.cnblogs.com/mrclr/p/15099923.html
Copyright © 2011-2022 走看看