随机数

题解(废话)

这部分作者神志不清的自说自话大家跳过也无妨的qwq……

这题做的人少的吓人,我也是听了f321dd巨佬讲课才来尝试做一做,个人觉得还是很有趣的题qwq。

话说这题网上题解似乎只有不超过 33 篇啊……像我这种菜鸡水平的人没什么题解看就很难受,所以千辛万苦过了这题来记录一下。

话说做这题的时候还有一个有趣的事儿,就是中途用瞪眼法已经再也瞪不出bug的时候,我去偷了一手Picks爷的代码对拍,结果拍出来四五个,手算之后发现错的全是Picks爷的代码qaq,定睛一看发现他在多项式快速幂的时候没有取模,如果 k 比 n 大一些他就裂开了……

顺便给大家送一组第二问的样例吧(应该是满足题目要求的……):

input :
5
1 0 1 0 0
1 0 0 0 0
1
2
1 0 1 0 1
output :
00011

真·题解

不说了上代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 3000010
#define mod 998244353
#define bin(x) (1<<(x))
#define MS(f,x) memset(f,0,4<<(x))
#define CP(f,g,x) memcpy(f,g,(x)<<2)

#define cn getchar
template<class TY>void read(TY &x){
    x=0;int f1=1;char ch=cn();
    while(ch<'0'||ch>'9'){if(ch=='-')f1=-1;ch=cn();}
    while(ch>='0'&&ch<='9')x=x*10+(ch-'0'),ch=cn(); x*=f1;
}
int n,F[maxn],G[maxn];
int ksm(int x,int y){int re=1;for(;(y&1?re=1ll*re*x%mod:0),y;y>>=1,x=1ll*x*x%mod);return re;}
int w[maxn],inv[maxn];void prep(int lg){int N=bin(lg);
    inv[1]=1;for(int i=2;i<=N;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=1,wn;i<N;i<<=1){
        w[i]=1;wn=ksm(3,(mod-1)/(i<<1));
        for(int j=1;j<i;j++)w[i+j]=1ll*w[i+j-1]*wn%mod;
    }
}
void reduce(int &x){x+=x>>31&mod;}
void ntt(int *f,int lg,int type=0){
    int limit=bin(lg);if(type)reverse(f+1,f+limit);
    for(int i=0,j=0,k;i<limit;i++){if(i<j)swap(f[i],f[j]);k=limit>>1;while((j^=k)<k)k>>=1;}
    for(int mid=1,t;mid<limit;mid<<=1)for(int j=0;j<limit;j+=(mid<<1))for(int i=0;i<mid;i++)
    {t=1ll*f[j|i|mid]*w[mid|i]%mod;reduce(f[j|i|mid]=f[j|i]-t);reduce(f[j|i]+=t-mod);}
    if(type)for(int i=0;i<limit;i++)f[i]=1ll*f[i]*inv[limit]%mod;
}
int A[maxn],B[maxn],C[maxn],D[maxn],E[maxn],Q[maxn],R[maxn];
void NTT(int *f,int *g,int ln,int Mul=2){
    int lg=ceil(log2(ln*Mul));ntt(f,lg);ntt(g,lg);
    for(int i=0;i<bin(lg);i++)f[i]=1ll*f[i]*g[i]%mod;ntt(f,lg,1);
    for(int i=0;i<bin(lg);i++)f[i]&=1;
}
void getsqr(int *f,int ln){
    int lg=ceil(log2(2*ln-1));
    ntt(f,lg);for(int i=0;i<bin(lg);i++)f[i]=1ll*f[i]*f[i]%mod;
    ntt(f,lg,1);for(int i=0;i<bin(lg);i++)f[i]&=1;
}
void getinv(int *f,int *g,int ln){
    if(ln==1){g[0]=ksm(f[0],mod-2);return;}getinv(f,g,ln+1>>1);
    int lg=ceil(log2(ln<<1));MS(A,lg);MS(B,lg);CP(A,f,ln);CP(B,g,ln);
    getsqr(B,ln+1>>1);NTT(B,A,ln);CP(g,B,ln);
}
void getrev(int *f,int *g,int ln){for(int i=0;i<=ln;i++)g[i]=f[ln-i];}
void getdiv(int *f,int *g,int *q,int ln1,int ln2){
    int lg=ceil(log2(ln1+1));MS(C,lg);MS(D,lg);MS(E,lg);
    getrev(f,C,ln1);getrev(g,D,ln2);for(int i=ln1-ln2+1;i<=ln1;i++)C[i]=D[i]=0;
    getinv(D,E,ln1-ln2+1);for(int i=0;i<=ln1-ln2;i++)E[i]&=1;
    NTT(C,E,ln1-ln2+1);getrev(C,q,ln1-ln2);
}
void getmod(int *f,int *g,int *q,int *r,int ln1,int ln2){
    int lg=ceil(log2(ln1+1));MS(C,lg);MS(D,lg);CP(C,g,ln2+1);CP(D,q,ln1-ln2+1);
    NTT(C,D,ln1+1,1);for(int i=0;i<ln2;i++)r[i]=f[i]^C[i];
}
void Modto(int *f,int *g,int ln1,int ln2){
    for(int i=0;i<=ln1;i++)f[i]&=1;
    getdiv(f,g,Q,ln1,ln2);getmod(f,g,Q,R,ln1,ln2);
    for(int i=0;i<=ln1;i++)f[i]=(i<ln2?R[i]:0);
}
int Base[maxn],A1[maxn];
void solve1(){
    int ts;read(ts);
    int lg=ceil(log2(n<<1));Base[1]=A1[0]=1;
    int c1=0,c2=1;
    for(;ts;ts>>=1){
        if(ts&1){
            if((c1+=c2)<n)A1[c1-c2]=0,A1[c1]=1;
            else NTT(A1,Base,n),ntt(Base,lg,1),Modto(A1,G,2*n-1,n);
        }
        if((c2<<=1)<n)Base[c2>>1]=0,Base[c2]=1;
        else getsqr(Base,n),Modto(Base,G,2*n-1,n);
    }
    NTT(F,A1,n);Modto(F,G,2*n-1,n);
    for(int i=0;i<n;i++)putchar(F[i]?'1':'0');
}
int Mk[maxn];
void ksm1(int *f,int ts){
    for(int i=1;i<=ts;i++)
        getsqr(f,n),Modto(f,G,2*n-1,n);
}
void ksm2(int *f,int ts){
    int lg=ceil(log2(n<<1));
    CP(A1,f,n);ntt(f,lg);
    for(int i=1;i<ts;i++){
        for(int i=0;i<bin(lg);i++)f[i]=1ll*f[i]*f[i]%mod;
        ntt(f,lg,1);Modto(f,G,2*n-1,n);
        ntt(f,lg);ntt(A1,lg);for(int i=0;i<bin(lg);i++)A1[i]=1ll*A1[i]*f[i]%mod;
        ntt(A1,lg,1);Modto(A1,G,2*n-1,n);
    }
    for(int i=0;i<bin(lg);i++)f[i]=(i<n?A1[i]:0);
}
void solve2(){
    int l;read(l);
    for(int i=0;i<n;i++)read(Mk[i]);
    ksm1(Mk,n-l);ksm1(F,n-l);ksm2(F,l);
    NTT(F,Mk,n);Modto(F,G,2*n-1,n);
    for(int i=0;i<n;i++)putchar(F[i]?'1':'0');
}

int main()
{
    read(n);prep(ceil(log2(n+1<<1)));
    for(int i=0;i<n;i++)read(G[i]);G[n]=1;
    for(int i=0;i<n;i++)read(F[i]);
    int type;read(type);
    if(type==0)solve1();
    else solve2();
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值