zoukankan      html  css  js  c++  java
  • LOJ #6261. 一个人的高三楼 NTT

    题目链接


    题意:求一个长度为(n)的数列的(k)阶前缀和对998244353取模的结果.((nle10^{5} kle2^{60}))

    设$$f_k(x)=sum_{i=0}{n-1}S_{i+1}{(k)}x^i$$

    [g(x)=sum_{i=0}^{n-1}x^i ]

    于是有$$f_k(x)g(x)equiv f_{k+1}(x)pmod{x^n}$$

    所求即$$g(x)^kf_0(x)$$

    直接快速幂 复杂度(O(n log n log k)) 无法通过此题

    考虑(g(x)^k)各项的意义,设$$g(x)k=sum_{i=0}{n-1}a_ix^i$$

    (a_i)即为有序地选k个([0,n-1])之间的整数,和为i的方案数,用插板法可得(a_i=inom{k-1+i}{i}),从而可以(O(n))(O(n log n))得到(g(x)^k)

    最后用(NTT)(f_0(x))(g(x)^k)合并

    总复杂度(O(n log n))

    #include<cstdio>
    #include<algorithm>
    #include<ctype.h>
    #include<string.h>
    #include<math.h>
    
    using namespace std;
    #define ll long long
    #define rep(i,x,y) for(int i=(x);i<=(y);++i)
    #define travel(i,x) for(int i=h[x];i;i=pre[i])
    
    inline char read() {
    	static const int IN_LEN = 1000000;
    	static char buf[IN_LEN], *s, *t;
    	return (s == t ? t = (s = buf) + fread(buf, 1, IN_LEN, stdin), (s == t ? -1 : *s++) : *s++);
    }
    template<class T>
    inline void read(T &x) {
    	static bool iosig;
    	static char c;
    	for (iosig = false, c = read(); !isdigit(c); c = read()) {
    		if (c == '-') iosig = true;
    		if (c == -1) return;
    	}
    	for (x = 0; isdigit(c); c = read()) x = ((x + (x << 2)) << 1) + (c ^ '0');
    	if (iosig) x = -x;
    }
    const int OUT_LEN = 10000000;
    char obuf[OUT_LEN], *ooh = obuf;
    inline void print(char c) {
    	if (ooh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), ooh = obuf;
    	*ooh++ = c;
    }
    template<class T>
    inline void print(T x) {
    	static int buf[30], cnt;
    	if (x == 0) print('0');
    	else {
    		if (x < 0) print('-'), x = -x;
    		for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
    		while (cnt) print((char)buf[cnt--]);
    	}
    }
    inline void flush() { fwrite(obuf, 1, ooh - obuf, stdout); }
    const int N = 1<<18, P = 998244353;
    ll k;
    int n, p, a[N], b[N];
    inline int Pow(ll x, int y=P-2){
    	ll ass=1;
    	for(; y; y>>=1, x=x*x%P) if(y&1) ass=ass*x%P;
    	return ass;
    }
    inline void NTT(int *f, int g){
    	for(int i=0, j=0; i<p; ++i){
    		if(i>j) swap(f[i], f[j]);
    		for(int k=p>>1; (j^=k)<k; k>>=1);
    	}
    	for(int i=1; i<p; i<<=1){
    		int w0=(g==1?Pow(3, (P-1)/i/2):Pow(Pow(3, (P-1)/i/2)));
    		for(int j=0; j<p; j+=i<<1){
    			int w=1;
    			for(int k=j; k<j+i; ++k){
    				int t=(ll)w*f[k+i]%P;
    				f[k+i]=(P+f[k]-t)%P;
    				f[k]=(f[k]+t)%P;
    				w=(ll)w*w0%P;
    			}
    		}
    	}
    	if(g==-1){
    		int I=Pow(p);
    		rep(i, 0, p-1) f[i]=(ll)f[i]*I%P;
    	}
    }
    int main() {
    	read(n), read(k);
    	rep(i, 0, n-1) read(a[i]);
    	b[0]=1;
    	rep(i, 1, n-1) b[i]=(k-1+i)%P*b[i-1]%P*Pow(i)%P;
    	for(p=1; p<n*2-1; p<<=1);
    	NTT(a, 1), NTT(b, 1);
    	rep(i, 0, p-1) a[i]=(ll)a[i]*b[i]%P;
    	NTT(a, -1);
    	rep(i, 0, n-1) print(a[i]), print('
    ');
    	return flush(), 0;
    }
    
  • 相关阅读:
    docker 简单使用
    apache 目录网站显示indexs
    MySQL索引失效的几种情况
    mysql 基本常用语句
    UNIX 版本
    B语言的发明者 Ken Thomson & C语言的发明者Dennis Ritchie
    My SQl 积累
    C# DGV多行选择
    C#中很模糊查询DGV中数据的两种方法
    网址
  • 原文地址:https://www.cnblogs.com/CMXRYNP/p/9406169.html
Copyright © 2011-2022 走看看