• luogu2000 拯救世界


    题目链接

    solution

    该博文刚写完,就不小心手残清空了,只好重写。

    生成函数练手题

    先写上这个式子(frac{1}{1-x}=1+x+x^2+x^3+x^4+...)

    题目中描述了两种限制。

    • 第一种限制:神石的块数必须是(t)的倍数,那么他的生成函数就是(1+x^t+x^{2t}+x^{3t}+...)。这就相当于用(x^t)替换掉了上方式子中的(x)。所以该生成函数就是(frac{1}{1-x^t})

    • 第二中限制:神石的数目不超过(t),那么他的生成函数就是(1+x+x^2+x^3+...+x^t)。我们将其看作((1+x+x^2+x^3+...)-(x^{t+1}+x^{t+2}+x^{t+3}+...))。第一个括号里的内容就是(frac{1}{1-x}),第二个括号里就相当于将最上方的式子每项都乘以(x^{t+1})。所以第二个括号里的内容就是(frac{x^{t+1}}{1-x})。所以该限制的生成函数就是(frac{1-x^{t+1}}{1-x})

    然后将所有的限制用生成函数描述出来,并相乘,所得多项式的第(n)项就是答案。

    这10个限制的生成函数相乘为(frac{1}{1-x^6}cdotfrac{1-x^{10}}{1-x}cdot frac{1-x^6}{1-x}cdotfrac{1}{1-x^4}cdot frac{1-x^8}{1-x}cdotfrac{1}{1-x^2}cdotfrac{1-x^2}{1-x}cdotfrac{1}{1-x^8}cdotfrac{1}{1-x^{10}}cdotfrac{1-x^4}{1-x})

    约分一下发现就是(frac{1}{(1-x)^5})

    由广义二项式定理(frac{1}{(1-x)^k}=sumlimits_{nge0}C_{n+k-1}^nx^n)

    所以第n项的系数就是(C_{n+4}^n=frac{(n+1)(n+2)(n+3)(n+4)}{24})

    n比较大,用NTT或者FFT优化高精乘即可。

    code

    /*
    * @Author: wxyww
    * @Date:   2020-04-16 09:31:03
    * @Last Modified time: 2020-04-16 10:17:08
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    const int N = 1000010,mod = 998244353;
    ll read() {
    	ll x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1; c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		x = x * 10 + c - '0'; c = getchar();
    	}
    	return x * f;
    }
    char s[N];
    struct BIGNUM {
    	int a[N],len;
    
    	void Read() {
    		scanf("%s",s);
    		len = strlen(s);
    		for(int i = 0;i < len;++i) a[i] = s[len - i - 1] - '0';
    	}
    }n,a1,a2,a3,a4;
    
    BIGNUM operator + (BIGNUM A,int x) {
    	A.a[0] += x;
    	for(int i = 0;i < A.len;++i) {
    		if(A.a[i] >= 10) {
    			 A.a[i + 1] += A.a[i] / 10;
    			 A.a[i] %= 10;
    			 if(i == A.len - 1) ++A.len;
    		}
    	}
    	return A;
    }
    BIGNUM operator / (BIGNUM A,int x) {
    	int now = 0;
    	for(int i = A.len - 1;i >= 0;--i) {
    		now = now * 10 + A.a[i];
    		A.a[i] = now / x;
    		now %= x;
    	}
    	while(!A.a[A.len - 1]) --A.len;
    	return A;
    }
    int qm(int x,int y) {
    	int ret = 1;
    	for(;y;y >>= 1,x = 1ll * x * x % mod)
    		if(y & 1) ret = 1ll * ret * x % mod;
    	return ret;
    }
    int rev[N];
    void NTT(int *a,int n,int xs) {
    	for(int i = 0;i <= n;++i) if(rev[i] > i) swap(a[i],a[rev[i]]);
    
    	for(int m = 2;m <= n;m <<= 1) {
    		ll w1 = qm(3,(mod - 1) / m);
    		if(xs == -1) w1 = qm(w1,mod - 2);
    		for(int i = 0;i < n;i += m) {
    			ll w = 1;
    			for(int k = 0;k < (m >> 1);++k) {
    				ll u = a[i + k],t = w * a[i + k + (m >> 1)] % mod;
    				a[i + k] = (u + t) % mod;a[i + k + (m >> 1)] = (u - t + mod) % mod;
    				w = w * w1 % mod;
    			}
    		}
    	}
    }
    
    int t1[N],t2[N];
    BIGNUM operator * (const BIGNUM &A,const BIGNUM &B) {
    	int len = A.len + B.len - 1;
    
    	int tot = 1;
    	while(tot <= len) tot <<= 1;
    
    	// printf("!!!%d
    ",tot);
    
    	for(int i = 0;i <= tot;++i)
    		rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? (tot >> 1) : 0);
    
    	memset(t1,0,sizeof(t1));memset(t2,0,sizeof(t2));
    
    	for(int i = 0;i < A.len;++i) t1[i] = A.a[i];
    	for(int i = 0;i < B.len;++i) t2[i] = B.a[i];
    
    	// printf("%d
    ",tot);
    
    	NTT(t1,tot,1);NTT(t2,tot,1);
    
    	
    	
    	for(int i = 0;i <= tot;++i) t1[i] = 1ll * t1[i] * t2[i] % mod;
    
    	NTT(t1,tot,-1);
    
    	// for(int i = 0;i <= tot;++i) printf("%d ",t1[i]);	puts("");
    	int tmp = qm(tot,mod - 2);
    	BIGNUM C;
    	C.len = len;
    	for(int i = 0;i <= tot;++i)
    		t1[i] = 1ll * t1[i] * tmp % mod;
    	for(int i = 0;i < C.len;++i) {
    		if(t1[i] >= 10) {
    			t1[i + 1] += t1[i] / 10;
    			t1[i] %= 10;
    			if(i == C.len - 1) ++C.len;
    		}
    			C.a[i] = t1[i];
    			// printf("%d ",t1[i]);
    	}
    	// printf("%d%d
    ",C.a[0],C.a[1]);
    	// puts("");
    	return C;
    }
    
    int main() {
    	n.Read();
    	// BIGNUM K = (n + 1) * (n + 2);
    	BIGNUM K = (n + 1) * (n + 2) * (n + 3) * (n + 4) / 24;
    	for(int i = K.len - 1;i >= 0;--i) printf("%d",K.a[i]);
    
    	return 0;
    }
    
  • 相关阅读:
    这可能是全网最轻量级、对MVVM支持最好、可定制性最高的开源WPF Chart控件了
    WPF源代码分析系列一:剖析WPF模板机制的内部实现(五)
    WPF源代码分析系列一:剖析WPF模板机制的内部实现(四)
    WPF源代码分析系列一:剖析WPF模板机制的内部实现(三)
    WPF源代码分析系列一:剖析WPF模板机制的内部实现(二)
    WPF源代码分析系列一:剖析WPF模板机制的内部实现(一)
    深入理解.NET/WPF内存泄漏
    Cocos2d-X3.0 刨根问底(九)----- 场景切换(TransitionScene)源码分析
    Cocos2d-X3.0 刨根问底(八)----- 场景(Scene)、层(Layer)相关源码分析
    Cocos2d-X3.0 刨根问底(七)----- 事件机制Event源码分析
  • 原文地址:https://www.cnblogs.com/wxyww/p/luogu2000.html
Copyright © 2020-2023  润新知