[题解] Luogu P2000 拯救世界

生成函数板子题......

要写高精,还要NTT优化......异常dl



这个并不难想啊......

一次召唤会涉及到\(10\)个因素,全部写出来,然后乘起来就得到了答案的生成函数,输出\(n\)次项的系数就好了。

下面把\(10\)个条件列一下

\[1 + x^6 + x^{12} + \cdots = \frac{1}{1-x^6}\]

\[1+x^2+x^3+\cdots+x^9 = \frac{1-x^{10}}{1-x}\]

\[1+x^2+x^3+x^4+x^5 = \frac{1-x^6}{1-x}\]

\[1+x^4+x^8+\cdots = \frac{1}{1-x^4}\]

\[1+x^2+x^3+\cdots+x^7 = \frac{1-x^8}{1-x}\]

\[1+x^2+x^4+\cdots = \frac{1}{1-x^2}\]

\[1+x = \frac{1-x^2}{1-x}\]

\[1+x^8+x^{16}+\cdots = \frac{1}{1-x^8}\]

\[1+x^{10}+x^{20}+\cdots = \frac{1}{1-x^{10}}\]

\[1+x^2+x^3 = \frac{1-x^4}{1-x}\]

全部乘起来,然后消掉一些分子分母,就是\(\frac{1}{(1-x)^5} = (-x+1)^{-5}\),假设\(|x|<1\)好了,然后二项式定理

\[
(-x+1)^{-5} = \sum\limits_{k=0}^{\infty} (-1)^{k} \frac{(-5)(-5-1)\cdots(-5-k+1)}{k!} x^k = \sum\limits_{i=0}^{\infty} \binom{k+4}{k} x^k
\]

所以答案就是\(\binom{n+4}{n} = \frac{(n+1)(n+2)(n+3)(n+4)}{24}\)

然而要写高精......还要NTT啥的优化一下......

好像其他语言都被卡了......

\(Code:\)

#include <bits/stdc++.h>
using namespace std;
const int N=6e5+10,P=998244353,gen=3,igen=(P+1)/gen;
inline int add(int x,int y){
    return x+y>=P?x+y-P:x+y;
}
inline int sub(int x,int y){
    return x-y<0?x-y+P:x-y;
}
inline int fpow(int x,int y){
    int ret=1; for(;y;y>>=1,x=1ll*x*x%P)
        if(y&1) ret=1ll*ret*x%P;
    return ret;
}
int rev[N];
void init(int n){
    for(int i=0;i<n;i++) rev[i]=rev[i>>1]>>1|((i&1)?n>>1:0);
}
void ntt(int *f,int n,int flg){
    for(int i=0;i<n;i++)
        if(rev[i]<i) swap(f[i],f[rev[i]]);
    for(int k=1,len=2;len<=n;len<<=1,k<<=1){
        int wn=fpow(flg==1?gen:igen,(P-1)/len);
        for(int i=0;i<n;i+=len)
            for(int w=1,j=i;j<i+k;j++,w=1ll*w*wn%P){
                int tmp=1ll*w*f[j+k]%P;
                f[j+k]=sub(f[j],tmp),f[j]=add(f[j],tmp);
            }
    }
    if(flg==-1){
        int inv=fpow(n,P-2);
        for(int i=0;i<n;i++) f[i]=1ll*f[i]*inv%P;
    }
}
struct BigInt{
    static const int bas=100,basl=2;
    int a[N],len;
    int &operator [] (int k1){return a[k1];}
    BigInt(char *s){
        len=strlen(s); reverse(s,s+len);
        for(int i=0;i<len;i++) s[i]-=48;
        for(int i=0;i<len;i+=basl)
            a[i>>1]=s[i]+s[i+1]*10;
        maintain();
    }
    BigInt(){memset(a,0,sizeof(a));len=0;}
    void maintain(){
        while(len&&!a[len-1])len--;
        while(a[len])a[len]+=a[len-1]/bas,a[len-1]%=bas,len++;
    }
    void mdf(){
        a[0]++; for(int i=0;i<len;i++) a[i+1]+=a[i]/bas,a[i]%=bas;
        maintain();
    }
    BigInt operator * (BigInt &k1){
        int n=len,m=k1.len; int limit=1;while(limit<=n+m-1)limit<<=1; init(limit);
        static int A[N],B[N];
        for(int i=0;i<limit;i++) A[i]=a[i],B[i]=k1[i];
        ntt(A,limit,1),ntt(B,limit,1);
        BigInt ans; ans.len=n+m;
        for(int i=0;i<limit;i++) ans[i]=1ll*A[i]*B[i]%P;
        ntt(ans.a,limit,-1);
        for(int i=0;i<ans.len;i++) ans[i+1]+=ans[i]/bas,ans[i]%=bas;
        ans.maintain();
        return ans;
    }
    BigInt operator /= (int q){
        int r=0;
        for(int i=len-1;i>=0;i--){
            int nw=r*100+a[i];
            a[i]=nw/q; r=nw%q;
        }
        maintain();
        return *this;
    }
    void print(){
        printf("%d",a[len-1]);
        for(int i=len-2;i>=0;i--) printf("%.02d",a[i]);
    }
}a[5],ans;
char s[1000010];
int main(){
    scanf("%s",s); a[1]=s;
    a[1].mdf();for(int i=2;i<=4;i++) a[i]=a[i-1],a[i].mdf();
    ans=a[1]*a[2]*a[3]*a[4];
    ans/=24;
    ans.print();
    return 0;
}

原文地址:https://www.cnblogs.com/wxq1229/p/12283226.html

时间: 2024-10-24 12:28:23

[题解] Luogu P2000 拯救世界的相关文章

luogu P2000 拯救世界

嘟嘟嘟 题目有点坑,要你求的多少大阵指的是召唤kkk的大阵数 * lzn的大阵数,不是相加. 看到这个限制条件,显然要用生成函数推一推. 比如第一个条件"金神石的块数必须是6的倍数",就是\(1 +x ^ 6 + x ^ {12} + \ldots\),也就是\(\frac{1 - x ^ {6n}}{1 - x ^ 6}\).当\(x \in (-1, 1)\)时,就变成了\(\frac{1}{1 - x ^ 6}\). 剩下的同理. 然后把这10个条件都乘起来,一顿化简,答案就是\

九九乘法表拯救世界【误

Private Sub Command1_Click() Dim i, j As Integer Label1.Caption = " 万岁!世界重新得到了和平!" Form1.Cls For i = 1 To 9 For j = 1 To i Print j; "x"; i; "="; j * i, Next j Print Next i End Sub Private Sub Command2_Click() Form1.Cls Label1

题解 luogu P1850 【换教室】

题解 luogu P1850 [换教室] 时间:2019.8.6 一晚上(约 3.5h 写完) 题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 \(2n\) 节课程安排在 \(n\) 个时间段上.在第 \(i\)(\(1 \leq i \leq n\))个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室 \(c_i\) 上课,而另一节课程在教室 \(d_i\) 进行. 在不提交任何申请的情况下,学生们需要

题解 luogu P5021 【赛道修建】

题解 luogu P5021 [赛道修建] 时间:2019.8.9 20:40 时间:2019.8.12 题目描述 C 城将要举办一系列的赛车比赛.在比赛前,需要在城内修建 \(m\) 条赛道. C 城一共有 \(n\) 个路口,这些路口编号为 \(1,2,\dots,n\),有 \(n-1\) 条适合于修建赛道的双向通行的道路,每条道路连接着两个路口.其中,第 \(i\) 条道路连接的两个路口编号为 \(a_i\) 和 \(b_i\),该道路的长度为 \(l_i\).借助这 \(n-1\) 条

题解 Luogu P2499: [SDOI2012]象棋

关于这道题, 我们可以发现移动顺序不会改变答案, 具体来说, 我们有以下引理成立: 对于一个移动过程中的任意一个移动, 若其到达的位置上有一个棋子, 则该方案要么不能将所有棋子移动到最终位置, 要么可以通过改变顺序使这一次移动合法 证明: 考虑到达位置上的那个棋子, 如果它没有到达最终位置, 则我们考虑将该棋子移至下一步, 如果下一步还有没有到达最终位置的棋子, 则也移动它 否则直接调换这两个棋子的移动顺序即可 好的我们去除了题目中的要求: 「移动过程中不能出现多颗棋子同时在某一格的情况」, 接

vijos 1225 拯救世界-紧急集合

这是道带权中位数的题,自己一想好像暑假的时候在 noi-openjudge 那个网站写题的时候看过类似的,那个时候的我蒟蒻, 不知道怎么办? 现在重新想起了这一类题,找个时间攻一下吧!毕竟这道题不难, (只要从左往右扫一次,和从右往左扫一次,我再一次可耻地看了题解),思考了一下二维的情况,应该不难,只是把x坐标和y坐标分开而已,加油! 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #def

题解 Luogu P3370

讲讲这题的几种做法: 暴力匹配法 rt,暴力匹配,即把字符串存起来一位一位判相等 时间复杂度$ O(n^2·m) $ 再看看数据范围 $n\le10^5,m\le10^3$ 当场爆炸.当然有暴力分 代码(20pts): #include <bits/stdc++.h> using namespace std; char c[100001][1001]; bool pd(int x, int y) { int l1 = strlen(c[x]), l2 = strlen(c[y]); if(l1

【技术宅拯救世界】在Windows Server2012上利用OpenVPN搭建自己的VPN服务器

写在前面的话:前段时间利用VPN免流特别火,我本来打算买一个,但后来发现其实都是用的OpenVPN搭建的,正好我手上有一个腾讯的云服务器,我一想不如就自己搭建一个吧,省点钱,结果就这样浪费了两天的时间,最大的问题在于网上关于用windows server搭建的教程异常的少,大部分都是cent os并且是脚本搭建的,我看了好多,看得我一头雾水...总算在我折腾服务器两天之后建好了属于自己的第一个VPN服务器,但是免流那块,四川联通失败,浪费了我两天的时间,但是为了避免以后搭建再次搭建VPN时发生问

#技术男拯救世界# 如何自动跳过12306的「查询失败」

我等屌丝用不起Windows,也没法装哪些高大上的抢票浏览器,只好苦逼的刷12306官网.但是刷12306的过程中老是遇到「查询失败」错误,一旦遇到,刷票就自动中断了,让人非常不爽.于是就自己写了下面这个小脚本,用来跳过失败错误并恢复刷票. 使 用方法:打开任何浏览器,登录12306网站,进入查询/刷票页面,打开开发者工具里的网页控制台(Chrome:查看->开发者 ->JavaScript控制台,Firefox:工具->网页开发者->网页控制台,Safari:先打开「首选项」-&