luoguP4705 玩游戏 多项式运算+NTT

十分有趣的多项式推式子题,多多积累.

code:

#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <string>
#define ll long long
#define ull unsigned long long
using namespace std;
namespace IO
{
    char buf[100000],*p1,*p2;
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd()
    {
        int x=0; char s=nc();
        while(s<‘0‘) s=nc();
        while(s>=‘0‘) x=(((x<<2)+x)<<1)+s-‘0‘,s=nc();
        return x;
    }
    void print(int x) {if(x>=10) print(x/10);putchar(x%10+‘0‘);}
    void setIO(string s)
    {
        string in=s+".in";
        string out=s+".out";
        freopen(in.c_str(),"r",stdin);
        // freopen(out.c_str(),"w",stdout);
    }
};
const int G=3;
const int N=4000005;
const int mod=998244353;
int A[N],B[N],w[2][N],mem[N*100],*ptr=mem,tmpa[N],tmpb[N],aa[N],bb[N];
inline int qpow(int x,int y)
{
    int tmp=1;
    for(;y;y>>=1,x=(ll)x*x%mod)     if(y&1) tmp=(ll)tmp*x%mod;
    return tmp;
}
inline int INV(int a) { return qpow(a,mod-2); }
inline void ntt_init(int len)
{
    int i,j,k,mid,x,y;
    w[1][0]=w[0][0]=1,x=qpow(3,(mod-1)/len),y=qpow(x,mod-2);
    for (i=1;i<len;++i) w[0][i]=(ll)w[0][i-1]*x%mod,w[1][i]=(ll)w[1][i-1]*y%mod;
}
void NTT(int *a,int len,int flag)
{
    int i,j,k,mid,x,y;
    for(i=k=0;i<len;++i)
    {
        if(i>k)    swap(a[i],a[k]);
        for(j=len>>1;(k^=j)<j;j>>=1);
    }
    for(mid=1;mid<len;mid<<=1)
        for(i=0;i<len;i+=mid<<1)
            for(j=0;j<mid;++j)
            {
                x=a[i+j], y=(ll)w[flag==-1][len/(mid<<1)*j]*a[i+j+mid]%mod;
                a[i+j]=(x+y)%mod;
                a[i+j+mid]=(x-y+mod)%mod;
            }
    if(flag==-1)
    {
        int rev=INV(len);
        for(i=0;i<len;++i)    a[i]=(ll)a[i]*rev%mod;
    }
}
inline void getinv(int *a,int *b,int len,int la)
{
    if(len==1) { b[0]=INV(a[0]);   return; }
    getinv(a,b,len>>1,la);
    int l=len<<1,i;
    memset(A,0,l*sizeof(A[0]));
    memset(B,0,l*sizeof(A[0]));
    memcpy(A,a,min(la,len)*sizeof(a[0]));
    memcpy(B,b,len*sizeof(b[0]));
    ntt_init(l);
    NTT(A,l,1),NTT(B,l,1);
    for(i=0;i<l;++i)  A[i]=((ll)2-(ll)A[i]*B[i]%mod+mod)*B[i]%mod;
    NTT(A,l,-1);
    memcpy(b,A,len<<2);
}
void get_dao(int *a,int *b,int len)
{
    for(int i=1;i<len;++i) b[i-1]=(ll)i*a[i]%mod;
    b[len-1]=0;
}
void get_jifen(int *a,int *b,int len)
{
    for(int i=1;i<len;++i) b[i]=(ll)INV(i)*a[i-1]%mod;
    b[0]=0;
}
void get_ln(int *a,int *b,int len,int la)
{
    int l=len<<1,i;
    memset(tmpa,0,l<<2);
    memset(tmpb,0,l<<2);
    get_dao(a,tmpa,min(len,la));
    getinv(a,tmpb,len,la);
    ntt_init(l);
    NTT(tmpa,l,1),NTT(tmpb,l,1);
    for(i=0;i<l;++i) tmpa[i]=(ll)tmpa[i]*tmpb[i]%mod;
    NTT(tmpa,l,-1);
    get_jifen(tmpa,b,len);
}
void get_exp(int *a,int *b,int len,int la)
{
    if(len==1) { b[0]=1; return; }
    int l=len<<1,i;
    get_exp(a,b,len>>1,la);
    for(i=0;i<l;++i)  aa[i]=bb[i]=0;
    for(i=0;i<(len>>1);++i) aa[i]=b[i];
    get_ln(b,bb,len,len>>1);
    for(i=0;i<len;++i) bb[i]=(ll)(mod-bb[i]+(i>la?0:a[i]))%mod;
    bb[0]=(bb[0]+1)%mod;
    ntt_init(l);
    NTT(aa,l,1),NTT(bb,l,1);
    for(i=0;i<l;++i) aa[i]=(ll)aa[i]*bb[i]%mod;
    NTT(aa,l,-1);
    for(i=0;i<len;++i)  b[i]=aa[i];
}
struct poly
{
    int len,*a;
    poly(){}
    poly(int l) {len=l,a=ptr,ptr+=l; }
    inline void rev() { reverse(a,a+len); }
    inline void fix(int l) {len=l,a=ptr,ptr+=l;}
    inline void get_mod(int l) { for(int i=l;i<len;++i) a[i]=0;  len=l;  }
    inline poly dao()
    {
        poly re(len-1);
        for(int i=1;i<len;++i)  re.a[i-1]=(ll)i*a[i]%mod;
        return re;
    }
    inline poly jifen()
    {
        poly c;
        c.fix(len+1);
        c.a[0]=0;
        for(int i=1;i<=len;++i) c.a[i]=(ll)a[i-1]*INV(i)%mod;
        return c;
    }
    inline poly Inv(int l)
    {
        int lim=1;
        while(lim<=l) lim<<=1;
        poly b(lim);
        getinv(a,b.a,lim,len);
        b.get_mod(l);
        return b;
    }
    inline poly ln(int l)
    {
        int lim=1;
        while(lim<=l) lim<<=1;
        poly b(lim);
        get_ln(a,b.a,lim,len);
        return b;
    }
    inline poly exp(int l)
    {
        int lim=1;
        while(lim<=l) lim<<=1;
        poly b(lim);
        get_exp(a,b.a,lim,len);
        b.get_mod(l);
        return b;
    }
    inline poly operator*(const poly &b) const
    {
        poly c(len+b.len-1);
        if(c.len<=500)
        {
            for(int i=0;i<len;++i)
                if(a[i])   for(int j=0;j<b.len;++j)  c.a[i+j]=(c.a[i+j]+(ll)(a[i])*b.a[j])%mod;
            return c;
        }
        int n=1;
        while(n<(len+b.len)) n<<=1;
        memset(A,0,n<<2);
        memset(B,0,n<<2);
        memcpy(A,a,len<<2);
        memcpy(B,b.a,b.len<<2);
        ntt_init(n);
        NTT(A,n,1), NTT(B,n,1);
        for(int i=0;i<n;++i) A[i]=(ll)A[i]*B[i]%mod;
        NTT(A,n,-1);
        memcpy(c.a,A,c.len<<2);
        return c;
    }
    poly operator+(const poly &b) const
    {
        poly c(max(len,b.len));
        for(int i=0;i<c.len;++i)  c.a[i]=((i<len?a[i]:0)+(i<b.len?b.a[i]:0))%mod;
        return c;
    }
    poly operator-(const poly &b) const
    {
        poly c(len);
        for(int i=0;i<len;++i)
        {
            if(i>=b.len)   c.a[i]=a[i];
            else c.a[i]=(a[i]-b.a[i]+mod)%mod;
        }
        return c;
    }
    poly operator/(poly u)
    {
        int n=len,m=u.len,l=1;
        while(l<(n-m+1)) l<<=1;
        rev(),u.rev();
        poly v=u.Inv(l);
        v.get_mod(n-m+1);
        poly re=(*this)*v;
        rev(),u.rev();
        re.get_mod(n-m+1);
        re.rev();
        return re;
    }
    poly operator%(poly u)
    {
        poly re=(*this)-u*(*this/u);
        re.get_mod(u.len-1);
        return re;
    }
}po;
poly solve(int l,int r,int *ar)
{
    if(l==r)
    {
        poly c;
        c.fix(2);
        c.a[0]=1;
        c.a[1]=mod-ar[l];
        return c;
    }
    int mid=(l+r)>>1;
    return solve(l,mid,ar)*solve(mid+1,r,ar);
}
#define MAX 100007
int n,m;
int bo[N],al[N],fac[N],inv[N];
int main()
{
    int i,j;
    // IO::setIO("input");
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;++i)   scanf("%d",&al[i]);
    for(i=1;i<=m;++i)   scanf("%d",&bo[i]);
    inv[0]=fac[0]=1;
    for(i=1;i<=MAX;++i) fac[i]=(ll)fac[i-1]*i%mod,inv[i]=INV(fac[i]);
    poly _A=solve(1,n,al);
    poly _B=solve(1,m,bo);
    _A=_A.dao()*_A.Inv(MAX);          

    _B=_B.dao()*_B.Inv(MAX);                  

    poly tmp(2);
    tmp.a[0]=0,tmp.a[1]=1;      

    _A=_A*tmp;
    _B=_B*tmp;
    for(i=0;i<MAX;++i) _A.a[i]=mod-_A.a[i],_B.a[i]=mod-_B.a[i];
    _A.a[0]=(ll)(_A.a[0]+n)%mod;
    _B.a[0]=(ll)(_B.a[0]+m)%mod;       

    for(i=0;i<MAX;++i)  _A.a[i]=(ll)_A.a[i]*inv[i]%mod;
    for(i=0;i<MAX;++i)  _B.a[i]=(ll)_B.a[i]*inv[i]%mod;         

    poly fin=_A*_B;               

    int T;
    scanf("%d",&T);
    for(i=1;i<=T;++i)
    {
        int re=(ll)fin.a[i]*fac[i]%mod*INV(n)%mod*INV(m)%mod;
        printf("%d\n",re);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/12237119.html

时间: 2024-10-13 11:01:18

luoguP4705 玩游戏 多项式运算+NTT的相关文章

云电脑玩游戏用手柄可以吗

今年可以说是云游戏大爆发的一年,在6月份的游戏盛会E3大展上,多家公司宣布与云游戏平台合作,面向云游戏平台用户制作游戏.提供服务.从去年开始,就有很多公司宣布开发云游戏平台,微软的Project xCloud,谷歌的Stadia等,都开了发布会,我们也看到他们同时推出了适用于云游戏平台的手柄,那么作为功能和云游戏平台类似的云电脑玩游戏用手柄可以吗?我们来看看吧. 云电脑的定义今年最火的云游戏平台应该非谷歌的stadia莫属了,它对于个人用户而言就是一台用来玩游戏的云电脑,不过云电脑并不是功能这么

跟王老师学Java三大特性(四):案例 QuickHit:玩家玩游戏

案例 QuickHit:玩家玩游戏 主讲教师:王少华   QQ群号:483773664 学习目标 完成Player类中的play方法 一.需求说明 玩家玩游戏 二.思路分析 创建Game对象并传入player属性: 外层循环(循环次数是6,每循环一次玩家级别升一级) 晋级: 积分清零.计时清零: 内层循环(循环次数是该级别的strTime,每循环一次完成一次人机交互) 游戏输出字符串: 玩家输入字符串: 游戏判断玩家输入并输出相应结果. 三.参考代码 1 2 3 4 5 6 7 8 9 10 1

UESTC_邱老师玩游戏 2015 UESTC Training for Dynamic Programming&lt;Problem G&gt;

G - 邱老师玩游戏 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 邱老师最近在玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中邱老师允许攻克M个城堡并获得里面的宝物. 但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡.你能帮邱老师算出要获得尽量多的宝物应该攻克哪M个城堡吗? In

像写诗一样写代码,玩游戏一样的开心心情,还能领工资!

[软]上海-Qt侠 2017/7/12 16:11:20我完全是兴趣主导,老板不给我钱,我也要写好代码!白天干,晚上干,周一周五干,周末继续干!编程已经深入我的基因,深入我的骨髓,深入我的灵魂!当我解决一个程序问题,比别人玩王者荣耀拿了第一名还开心!你要想想,能干自己感兴趣的事情,像写诗一样写代码,玩游戏一样的开心心情,还能领工资!真他妈爽!没有比这个更爽的事情!

[BZOJ4730][清华集训2016][UOJ266] Alice和Bob又在玩游戏

题意:俩智障又在玩游戏.规则如下: 给定n个点,m条无向边(m<=n-1),保证无环,对于每一个联通块,编号最小的为它们的根(也就是形成了一片这样的森林),每次可以选择一个点,将其本身与其祖先全部删除,不能操作者输.判断先手胜负. 题解:比较神的一道题. 我们现在要解决的问题是怎么求解一棵子树的SG值,首先把根删掉的情况考虑,这很好办,直接把子树的sg异或起来就好,关键是如果删除点在子树里怎么办. 这里用到了一个巧妙的东西,trie.怎么会用这个呢?因为删除子树里的节点就相当于是子树里这种对应的

小易邀请你玩一个数字游戏,小易给你一系列的整数。你们俩使用这些整数玩游戏。每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字。 例如: 如果{2,1,2,7}是你有的一系列数,小易说的数字是11.你可以得到方案2+2+7 = 11.如果顽皮的小易想坑你,他说的数字是6,那么你没有办法拼凑出和为6 现在小易给你n个数,让你找出无法从n个数中选取部分求和

小易邀请你玩一个数字游戏,小易给你一系列的整数.你们俩使用这些整数玩游戏.每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字. 例如: 如果{2,1,2,7}是你有的一系列数,小易说的数字是11.你可以得到方案2+2+7 = 11.如果顽皮的小易想坑你,他说的数字是6,那么你没有办法拼凑出和为6 现在小易给你n个数,让你找出无法从n个数中选取部分求和的数字中的最小数. 输入描述: 输入第一行为数字个数n (n ≤ 20) 第二行为n个数xi (1

【用PS3手柄在安卓设备上玩游戏系列】FC(任天堂NES/FC主机)模拟器

NESoid 是安卓系统下公认最好的FC模拟器.据我所知,现在安卓系统下面的绝大部分的FC模拟器,都是基于 NESoid 的内核来开发的. 官方网站:http://www.nesoid.com NESoid 是原生支持实体手柄的,下面以<超级魂斗罗>为例说明我的设置步骤: Step1:运行 SixaxisController(以下简称 SC),连接手柄和设备,我的设备是小米2: Step2:扩展菜单按钮 > 设置 > 手柄设置,勾选"启用手柄",然后选择&quo

【现身说法】玩游戏不如自己开发游戏

内容简介 [现身说法]玩游戏不如自己开发游戏 自己开发游戏比玩游戏好玩100倍 现在这个时代,众多智能产品的出现,使得游戏市场风云变换.一时间,手游和更新奇的游戏形式(例如虚拟现实)成了继小霸王,街机,Game Boy,PS,PC游戏之后的又一霸主. 这也使得玩游戏的人数与日俱增,App Store和Google Play这两个iOS和Android最大的App平台,超过60%是游戏类App.下图是2015第一季度Google Play的App分配比例: 我国的先辈们说过:"先天下之忧而忧,后天

精品软件 推荐 常用软件 游戏的 运行库 下载 合集 玩游戏的一定要收藏一下。

我们一般玩游戏的话,都会要装Visual C++ 运行库, Microsoft .NET Framework, DirectX 9.0, Rapture3D 2.6.5 Game ,Open Audio Library 2.1.0 (OpenAL) ,NVIDIA PhysX System Software 9.14.0702, video card drivers 显卡驱动等. 我分享一下下载地址,另外有一个网友做了一个合集,太好了.分享一下他的网页. 下面蓝色是我整理的部分地址,因为找到3d