有什么卡常技巧
查看原帖
有什么卡常技巧
504093
dyc2022楼主2025/7/26 14:24

rt,多点求值第一个点跑了 19s。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define N 300006
using namespace std;
inline int read()
{
	int ret=0,f=1;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')f=-1,ch=getchar();
	while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();
	return ret*f;
}
inline void write(int k)
{
	if(k<0)putchar('-'),k=-k;
	int nnum[20],ttp=0;
	while(k)nnum[++ttp]=k%10,k/=10;
	if(!ttp)nnum[++ttp]=0;
	while(ttp)putchar(nnum[ttp--]^48);
}
namespace POLY{
const int MOD=998244353,G=3,invg=(MOD+1)/3;
int r[N];
inline int qpow(int x,int y)
{
    if(y==0)return 1;
    if(y==1)return x%MOD;
    int ret=qpow(x,y>>1);
    return ret*ret%MOD*qpow(x,y&1)%MOD;
}
inline void NTT(int len,int *a,int opt)
{
    for(int i=0;i<len;i++)if(i<r[i])
        swap(a[i],a[r[i]]);
    for(int i=1;i<len;i<<=1)
    {
        int tmp=i<<1,Wn=qpow(opt==1?G:invg,(MOD-1)/tmp);
        for(int j=0;j<len;j+=tmp)
        {
            int w=1,x,y;
            for(int k=0;k<i;k++,w=w*Wn%MOD)
                x=a[j+k],y=w*a[i+j+k]%MOD,a[j+k]=(x+y)%MOD,a[i+j+k]=(x+MOD-y)%MOD;
        }
    }
    if(opt!=1)
    {
        int invn=qpow(len,MOD-2);
        for(int i=0;i<len;i++)a[i]=a[i]*invn%MOD;
    }
}
inline void times(int n,int m,int *a,int *b,int *ans)
{
    int len=1,lg=0;
    while(len<=n+m)len<<=1,lg++;
    for(int i=0;i<len;i++)
        r[i]=(r[i>>1]>>1)|((i&1)<<lg-1);
    NTT(len,a,1),NTT(len,b,1);
    for(int i=0;i<=len;i++)a[i]=a[i]*b[i]%MOD;
    NTT(len,a,-1);
    for(int i=0;i<=n+m;i++)ans[i]=a[i];
}
int c[N];
inline void getinv(int n,int *a,int *b)
{
	if(n==1)return b[0]=qpow(a[0],MOD-2),(void)0;
	getinv(n+1>>1,a,b);
	int len=1,lg=0;
	while(len<(n<<1))len<<=1,lg++;
	for(int i=0;i<len;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(lg-1));
	for(int i=0;i<n;i++)c[i]=a[i];
	for(int i=n;i<len;i++)c[i]=0;
	NTT(len,c,1),NTT(len,b,1);
	for(int i=0;i<len;i++)
		b[i]=(2+MOD-c[i]*b[i]%MOD)%MOD*b[i]%MOD;
	NTT(len,b,-1);
	for(int i=n;i<len;i++)b[i]=0;
	memset(c,0,sizeof(c));
}
int f[N],g[N],fr[N],gr[N],invgr[N],dr[N],td[N],tmp[N];
inline void modulo(int n,int m,int *tf,int *tg,int *r)
{
    for(int i=0;i<n+m<<1;i++)
        f[i]=g[i]=fr[i]=gr[i]=invgr[i]=dr[i]=tmp[i]=td[i]=0;
    for(int i=0;i<n;i++)f[i]=tf[i];
    for(int i=0;i<m;i++)g[i]=tg[i];
    for(int i=0;i<n;i++)fr[n-i-1]=f[i];
    for(int i=0;i<m;i++)gr[m-i-1]=g[i];
    getinv(n-m+1,gr,invgr),times(n,n-m+1,fr,invgr,dr);
    for(int i=n-m;~i;i--)td[n-m-i]=dr[i];
    times(m,n-m+1,g,td,tmp);
    for(int i=0;i<m-1;i++)
        r[i]=(f[i]+MOD-tmp[i])%MOD;
}
int *p[N<<2],length[N<<2],ta[N],tb[N];
void init(int len,int lg){for(int i=0;i<len;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(lg-1));}
void getp(int u,int l,int r,int *a)
{
    length[u]=r-l+1,p[u]=new int[length[u]+1];
    if(l==r)
        return p[u][0]=(MOD-a[l]),p[u][1]=1,(void)0;
    int mid=l+r>>1;
    getp(u<<1,l,mid,a),getp(u<<1|1,mid+1,r,a);
    int len=1,lg=0;
    while(len<(length[u]+1<<1))len<<=1,lg++;
    init(len,lg);
    for(int i=0;i<=length[u<<1];i++)ta[i]=p[u<<1][i];
    for(int i=length[u<<1]+1;i<len;i++)ta[i]=0;
    for(int i=0;i<=length[u<<1|1];i++)tb[i]=p[u<<1|1][i];
    for(int i=length[u<<1|1]+1;i<len;i++)tb[i]=0;
    NTT(len,ta,1),NTT(len,tb,1);
    for(int i=0;i<len;i++)ta[i]=ta[i]*tb[i]%MOD;
    NTT(len,ta,-1);
    for(int i=0;i<=length[u];i++)p[u][i]=ta[i];
}
void solve(int u,int l,int r,int *a,int *f,int *ans)
{
    if(l==r)return ans[l]=*f,(void)0;
    int mid=l+r>>1,md[length[u]+2]={0};
    modulo(length[u],length[u<<1]+1,f,p[u<<1],md);
    solve(u<<1,l,mid,a,md,ans);
    modulo(length[u],length[u<<1|1]+1,f,p[u<<1|1],md);
    solve(u<<1|1,mid+1,r,a,md,ans);
}
void evaluation(int n,int m,int *a,int *f,int *ans)
{
    getp(1,1,m,a);
    if(n>m)modulo(n,m+1,f,p[1],f);
    solve(1,1,m,a,f,ans);
}
}
int n,m,a[N],f[N],ans[N];
main()
{
    n=read()+1,m=read();
    for(int i=0;i<n;i++)f[i]=read();
    for(int i=1;i<=m;i++)a[i]=read();
    POLY::evaluation(n,m,a,f,ans);
    for(int i=1;i<=m;i++)write(ans[i]),putchar(10);
    return 0;
}
2025/7/26 14:24
加载中...