• 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;
    }
    
  • 相关阅读:
    【公告】阿里云出现问题:镜像创建的服务器无法启动团队
    上周热点回顾(4.8-4.14)团队
    上周热点回顾(4.1-4.7)团队
    【故障公告】阿里云抢占式实例服务器被自动释放引发的故障团队
    上周热点回顾(3.25-3.31)团队
    上周热点回顾(3.18-3.24)团队
    上周热点回顾(3.11-3.17)团队
    博客园 .NET Core 线下技术交流会 -- 上海站团队
    分区助手是什么?(博主推荐)(图文详解)
    IDEA里点击Build,再Build Artifacts没反应,灰色的?解决办法(图文详解)
  • 原文地址:https://www.cnblogs.com/mrclr/p/15099923.html
Copyright © 2020-2023  润新知