P2000 拯救世界(生成函数,NTT加速高精乘)

53 篇文章 0 订阅
44 篇文章 0 订阅

P2000 拯救世界

题意:
  • 10 10 10 种用混沌之石的方法生成大阵,求 n n n 块神石能生成的大阵数量
分析:
  • 生成函数板子题 + + + 快速高精乘( N T T NTT NTT 优化)
  • 下面列出十种神石的生成函数
  1. f ( x ) = 1 + x 6 + x 12 + x 18 + . . . = 1 1 − x 6 f(x)=1+x^6+x^{12}+x^{18}+...=\frac{1}{1-x^6} f(x)=1+x6+x12+x18+...=1x61

  2. f ( x ) = 1 + x + x 2 + x 3 + . . . + x 9 = 1 − x 10 1 − x f(x)=1+x+x^2+x^3+...+x^9=\frac{1-x^{10}}{1-x} f(x)=1+x+x2+x3+...+x9=1x1x10

  3. f ( x ) = 1 + x + x 2 + x 3 + . . . + x 5 = 1 − x 6 1 − x f(x)=1+x+x^2+x^3+...+x^5=\frac{1-x^{6}}{1-x} f(x)=1+x+x2+x3+...+x5=1x1x6

  4. f ( x ) = 1 + x 4 + x 8 + x 12 + . . . = 1 1 − x 4 f(x)=1+x^4+x^8+x^{12}+...=\frac{1}{1-x^4} f(x)=1+x4+x8+x12+...=1x41

  5. f ( x ) = 1 + x + x 2 + x 3 + . . . + x 7 = 1 − x 8 1 − x f(x)=1+x+x^2+x^3+...+x^7=\frac{1-x^{8}}{1-x} f(x)=1+x+x2+x3+...+x7=1x1x8

  6. f ( x ) = 1 + x 2 + x 4 + x 6 + . . . = 1 1 − x 2 f(x)=1+x^2+x^4+x^6+...=\frac{1}{1-x^2} f(x)=1+x2+x4+x6+...=1x21

  7. f ( x ) = 1 + x = 1 − x 2 1 − x f(x)=1+x=\frac{1-x^2}{1-x} f(x)=1+x=1x1x2

  8. f ( x ) = 1 + x 8 + x 16 + x 24 + . . . = 1 1 − x 8 f(x)=1+x^8+x^{16}+x^{24}+...=\frac{1}{1-x^8} f(x)=1+x8+x16+x24+...=1x81

  9. f ( x ) = 1 + x 10 + x 20 + x 30 + . . . = 1 1 − x 10 f(x)=1+x^{10}+x^{20}+x^{30}+...=\frac{1}{1-x^{10}} f(x)=1+x10+x20+x30+...=1x101

  10. f ( x ) = 1 + x + x 2 + x 3 = 1 − x 4 1 − x f(x)=1+x+x^2+x^3=\frac{1-x^{4}}{1-x} f(x)=1+x+x2+x3=1x1x4

    10 10 10 个式子相乘得到总的生成函数:
    ( 1 − x 10 ) ( 1 − x 6 ) ( 1 − x 8 ) ( 1 − x 2 ) ( 1 − x 4 ) ( 1 − x 6 ) ( 1 − x ) 5 ( 1 − x 4 ) ( 1 − x 2 ) ( 1 − x 8 ) ( 1 − x 10 ) = ( 1 − x ) − 5 \frac{(1-x^{10})(1-x^{6})(1-x^{8})(1-x^{2})(1-x^{4})}{(1-x^{6})(1-x^{})^5(1-x^{4})(1-x^{2})(1-x^{8})(1-x^{10})}=(1-x)^{-5} (1x6)(1x)5(1x4)(1x2)(1x8)(1x10)(1x10)(1x6)(1x8)(1x2)(1x4)=(1x)5
    再根据牛顿广义二项式定理:

    ( 1 − x ) − n = ∑ i = 0 ∞ ( i n + i − 1 ) x i (1-x)^{-n} = \sum^{\infty}_{i=0}(^{n+i-1}_i)x^i (1x)n=i=0(in+i1)xi
    答案即为: ( 4 n + 4 ) = ( n + 4 ) ( n + 3 ) ( n + 2 ) ( n + 1 ) 24 (^{n+4}_4)=\frac{(n+4)(n+3)(n+2)(n+1)}{24} (4n+4)=24(n+4)(n+3)(n+2)(n+1)

    N T T NTT NTT 加速高精乘计算即可

#include<bits/stdc++.h>
#define int long long 
using namespace std;

const int N = (1<<22)+5, mo=998244353;

int rev[N];
void init(int k)
{
    int s=1<<k;
    for(int i=1;i<s;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
}
int binpow(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1) ans = ans*a%mo;
        a = a*a%mo;
        b >>= 1;
    }
    return ans;
}
void ntt(int *a, int n, int inv)
{
	for(int i=0;i<n;i++)
    {
		if(i < rev[i]) swap(a[i], a[rev[i]]);
    }
	for(int len=1;len<n;len<<=1) 
    {	
		int Wn = binpow(3, (mo-1)/(len<<1));
        if(inv == -1) Wn = binpow(Wn, mo-2);
		for(int i=0;i<n;i+=(len<< 1)) 
        {
			int w=1;
			for(int j=0;j<len;j++, w = (w*Wn)%mo) 
            {
				int x = a[i + j], y = w*a[i+j+len]%mo;
				a[i+j] = (x+y)%mo; a[i+j+len] = (x-y+mo)%mo;
			}
		}
	}
    if(inv == -1)
    {
        int fg=binpow(n, mo-2);
        for(int i=0;i<n;i++) a[i] = a[i]*fg%mo;
    }
}
void pre(int *a,int *b,int &n,int m)
{
    int s=2, k=1;
    while(s < n+m-1) k++, s <<= 1;
    init(k);
    ntt(a,s,1); ntt(b,s,1);
    for(int i=0;i<s;i++) a[i] *= b[i];
    ntt(a,s,-1); ntt(b,s,-1); 
    for(int i=0;i<s;i++) 
    {
        a[i+1] += a[i]/10;
        a[i] %= 10;
    }
    while(!a[s] && s>-1) s--;
    n = s+1;
}
int a[N], b[N];
char s[N];
signed main()
{
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
    cin>>s;
    int n=strlen(s);
    for(int i=0;i<n;i++) a[i] = b[i] = s[n-i-1]-'0';
    a[0]++; b[0]++;
    int la=n, lb=n;
    for(int i=1;i<4;i++)
    {
        b[0]++;
        pre(a,b,la,lb);
    }
    int fg=0;
    for(int i=la-1;i>=0;i--)
    {
        if(i) a[i-1] += (a[i]%24)*10;
        a[i] /= 24;
        if(a[i] || fg) fg=1, cout<<a[i];
    }

	return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yezzz.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值