zoukankan      html  css  js  c++  java
  • BJOI2018简要题解

    R1T1二进制

    发现一个二进制中的(1)对这个数模(3)的结果有(1)(2)的贡献

    所以当序列有偶数个(1)时,重排后就珂以

    当序列里有奇数个(1)且个数不为(1),有至少(2)(0)时,重排后就珂以

    我们考虑用总数减去不合法的得出答案

    首先,根据上面的结论,我们每次珂以线性得出答案,但是只有(50pts)

    考虑动态dp,线段树维护

    每个节点维护(dl[0/1][0/1]),表示左边一段连续区间中有(0/1)(0)(1)个数的奇偶性为(0/1)的个数,类似的维护(dr)

    还要维护(fl[0/1/2]),表示左边一段连续取件有(0/1/2)(0)(1)(1)的个数,类似的维护(fr)

    转移显然,这样我们就得到了一个(O((n+m)log n))的做法

    #include <bits/stdc++.h>
    #define ll long long
    #define N 100005
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register ll x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    struct data{
        ll dl[2][2],dr[2][2],fl[3],fr[3],s;
        int l0,r0,s0,s1;
        inline void init()
        {
            dl[0][0]=dl[0][1]=dl[1][0]=dl[1][1]=dr[0][0]=dr[0][1]=dr[1][0]=dr[1][1]=0;
            fl[0]=fl[1]=fl[2]=fr[0]=fr[1]=fr[2]=0;
            l0=r0=s0=s1=s=0;
        }
        inline void pre(register int x)
        {
            init();
            if(x)
                dl[0][1]=dr[0][1]=s1=s=fl[0]=fr[0]=1;
            else
                dl[1][0]=dr[1][0]=s0=l0=r0=1;
        }
    }tr[N<<2];
    int n,a[N],m;
    inline data pushup(register data A,register data B)
    {
        data c;
        c.init();
        for(register int i=0;i<=1;++i)
            for(register int j=0;j<=1;++j)
            {
                c.dl[i][j]+=A.dl[i][j];
                c.dr[i][j]+=B.dr[i][j];
                if(i>=A.s0)
                    c.dl[i][j]+=B.dl[i-A.s0][j^(A.s1&1)];
                if(i>=B.s0)
                    c.dr[i][j]+=A.dr[i-B.s0][j^(B.s1&1)];
            }
        for(register int i=0;i<=2;++i)
        {
            c.fl[i]+=A.fl[i];
            c.fr[i]+=B.fr[i];
            if(!A.s1)
                c.fl[min(2,i+A.s0)]+=B.fl[i];
            if(!B.s1)
                c.fr[min(2,i+B.s0)]+=A.fr[i];
        }
        if(A.s1==1&&B.l0)
            ++c.fl[min(2,A.s0+B.l0)],c.fl[2]+=B.l0-1;
        if(B.s1==1&&A.r0)
            ++c.fr[min(2,B.s0+A.r0)],c.fr[2]+=A.r0-1;
        c.l0=(A.s1==0)?A.s0+B.l0:A.l0;
        c.r0=(B.s1==0)?B.s0+A.r0:B.r0;
        c.s0=A.s0+B.s0;
        c.s1=A.s1+B.s1;
        c.s=A.s+B.s;
        c.s+=A.dr[0][0]*(B.dl[0][1]+B.dl[1][1]);
        c.s+=A.dr[0][1]*(B.dl[0][0]+B.dl[1][0]);
        c.s+=A.dr[1][0]*B.dl[0][1];
        c.s+=A.dr[1][1]*B.dl[0][0];
        if(B.l0)
            c.s+=B.l0*(A.fr[0]+A.fr[1]+A.fr[2])-A.fr[0];
        if(A.r0)
            c.s+=A.r0*(B.fl[0]+B.fl[1]+B.fl[2])-B.fl[0];
        return c;
    }
    inline void build(register int x,register int l,register int r)
    {
        if(l==r)
        {
            tr[x].pre(a[l]);
            return;
        }
        int mid=l+r>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        tr[x]=pushup(tr[x<<1],tr[x<<1|1]);
    }
    inline void modify(register int x,register int l,register int r,register int pos)
    {
        if(l==r)
        {
            tr[x].pre(a[l]);
            return;
        }
        int mid=l+r>>1;
        if(pos<=mid)
            modify(x<<1,l,mid,pos);
        else
            modify(x<<1|1,mid+1,r,pos);
        tr[x]=pushup(tr[x<<1],tr[x<<1|1]);
    }
    inline data query(register int x,register int l,register int r,register int L,register int R)
    {
        if(L<=l&&r<=R)
            return tr[x];
        int mid=l+r>>1;
        if(R<=mid)
            return query(x<<1,l,mid,L,R);
        else if(L>mid)
            return query(x<<1|1,mid+1,r,L,R);
        else
            return pushup(query(x<<1,l,mid,L,R),query(x<<1|1,mid+1,r,L,R));
    }
    int main()
    {
        n=read();
        for(register int i=1;i<=n;++i)
            a[i]=read();
        build(1,1,n);
        m=read();
        while(m--)
        {
            int opt=read();
            if(opt==1)
            {
                int pos=read();
                a[pos]^=1;
                modify(1,1,n,pos);
            }
            else
            {
                int l=read(),r=read();
                write(1ll*(r-l+1)*(r-l+2)/2-query(1,1,n,l,r).s),puts("");
            }
        }
    	return 0;
    }
    

    R1T2染色

    神仙结论题

    对于每个联通块分别考虑

    首先,有奇环肯定不行

    边数大于(n+1)肯定不行,至少有三个环

    边数小于等于(n)的一定珂以

    边数等于(n+1)的要拓扑排序特判一下

    证明

    #include <bits/stdc++.h>
    #define N 20005
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    struct node{
        int to,nxt;
    }e[N<<1];
    int head[N>>1],cnt=0,du[N>>1];
    inline void add(register int u,register int v)
    {
        e[++cnt]=(node){v,head[u]};
        head[u]=cnt;
    }
    int T,n,m,col[N>>1],f,vtot,etot;
    vector <int> pt;
    queue <int> q;
    inline void dfs(register int x,register int cl)
    {
        if(f)
            return;
        if(col[x]!=-1)
        {
            if(col[x]!=cl)
                f=1;
            return;
        }
        col[x]=cl,++vtot,pt.push_back(x);
        for(register int i=head[x];i;i=e[i].nxt)
        {
            int v=e[i].to;
            ++etot;
            dfs(v,cl^1);
        }
    }
    int main()
    {
        T=read();
        while(T--)
        {
            cnt=f=0;
            memset(head,0,sizeof(head));
            memset(du,0,sizeof(du));
            memset(col,-1,sizeof(col));
            n=read(),m=read();
            for(register int i=1;i<=m;++i)
            {
                int u=read(),v=read();
                add(u,v),add(v,u);
                ++du[u],++du[v];
            }
            for(register int i=1;i<=n;++i)
                if(col[i]==-1)
                {
                    vtot=etot=0;
                    pt.clear();
                    dfs(i,0);
                    if(f)
                        break;
                    if(etot/2>vtot+1)
                    {
                        f=1;
                        break;
                    }
                    if(etot/2<=vtot)
                        continue;
                    for(register int j=0;j<pt.size();++j)
                        if(du[pt[j]]==1)
                            q.push(pt[j]);
                    while(!q.empty())
                    {
                        int u=q.front();
                        q.pop();
                        for(register int j=head[u];j;j=e[j].nxt)
                        {
                            int v=e[j].to;
                            if(--du[v]==1)
                                q.push(v);
                        }
                    }
                    int tot=0;
                    for(register int j=0;j<pt.size();++j)
                        if(du[pt[j]]==2)
                        {
                            int tmp=0;
                            for(register int k=head[pt[j]];k;k=e[k].nxt)
                                if(du[e[k].to]==3)
                                    ++tmp;
                            if(tmp==2)
                                ++tot;
                        }
                    if(tot<2)
                    {
                        f=1;
                        break;
                    }
                }
                puts(f?"NO":"YES");
        }
    	return 0;
    }
    

    R1T3求和

    观察到(k)的值域很小是([1,50]),我们可以暴力预处理,并做个前缀和,查询树上差分即可,复杂度(O(50n+m log n))

    #include <bits/stdc++.h>
    #define mod 998244353
    #define N 300005
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    struct node{
        int to,nxt;
    }e[N<<1];
    int head[N],cnt;
    inline void add(register int u,register int v)
    {
        e[++cnt]=(node){v,head[u]};
        head[u]=cnt;
    }
    int n,m,f[N][51],dep[N],siz[N],son[N],fa[N],top[N];
    inline void dfs1(register int x,register int fat)
    {
        siz[x]=1;
        for(register int i=head[x];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v==fat)
                continue;
            dep[v]=dep[x]+1;
            for(register int j=1,t=dep[v];j<=50;++j,t=1ll*t*dep[v]%mod)
                f[v][j]=(0ll+f[x][j]+t)%mod;
            dfs1(v,x);
            fa[v]=x;
            siz[x]+=siz[v];
            if(siz[v]>siz[son[x]])
                son[x]=v;
        }
    }
    inline void dfs2(register int x,register int t)
    {
        top[x]=t;
        if(son[x])
            dfs2(son[x],t);
        for(register int i=head[x];i;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v==fa[x]||v==son[x])
                continue;
            dfs2(v,v);
        }
    }
    inline int getlca(register int x,register int y)
    {
        int fx=top[x],fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx]<dep[fy])
                swap(fx,fy),swap(x,y);
            x=fa[fx];
            fx=top[x];
        }
        return dep[x]<dep[y]?x:y;
    }
    int main()
    {
        n=read();
        for(register int i=1;i<n;++i)
        {
            int u=read(),v=read();
            add(u,v),add(v,u);
        }
        dfs1(1,0);
        dfs2(1,1);
        int m=read();
        while(m--)
        {
            int u=read(),v=read(),k=read();
            int lca=getlca(u,v);
            write((0ll+f[u][k]+f[v][k]-f[lca][k]-f[fa[lca]][k]+2ll*mod)%mod),puts("");
        }
    	return 0;
    }
    

    R2T1双人猜数游戏

    神仙提答

    (f_{x,y,k})表示(x,y)两个数,进行(k)轮,是否已经确定,暴力转移即可

    #include <bits/stdc++.h>
    #define N 300
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    int s,t;
    char c;
    int f[N+1][N+1][20];
    inline int calc1(register int x,register int y,register int k)
    {
        int num=x*y,up=sqrt(x*y),xx=0,yy=0,cnt=0;
        for(register int i=s;i<=up;++i)
            if(num%i==0&&(!k||!f[i][num/i][k-1]))
                xx=i,yy=num/i,++cnt;
        return cnt==1&&xx==x&&yy==y;
    }
    inline int calc2(register int x,register int y,register int k)
    {
        int num=x+y,up=x+y>>1,xx=0,yy=0,cnt=0;
        for(register int i=s;i<=up;++i)
            if(!k||!f[i][num-i][k-1])
                xx=i,yy=num-i,++cnt;
        return cnt==1&&xx==x&&yy==y;
    }
    inline int calc3(register int x,register int y)
    {
        int num=x*y,up=sqrt(x*y),xx=0,yy=0,cnt=0;
        for(register int i=s;i<=up;++i)
            if(num%i==0&&f[i][num/i][t]&&(t<2||!f[i][num/i][t-2]))
                xx=i,yy=num/i,++cnt;
        return cnt==1&&xx==x&&yy==y;
    }
    inline int calc4(register int x,register int y)
    {
        int num=x+y,up=x+y>>1,xx=0,yy=0,cnt=0;
        for(register int i=s;i<=up;++i)
            if(f[i][num-i][t]&&(t<2||!f[i][num-i][t-2]))
                xx=i,yy=num-i,++cnt;
        return cnt==1&&xx==x&&yy==y;
    }
    inline void Work(register int x,register int y)
    {
        if(!f[x][y][t])
            return;
        for(register int k=0;k<t;++k)
            if(f[x][y][k])
                return;
        int nw=((t&1)&&c=='A')||(!(t&1)&&c=='B');
        int fl=nw?calc3(x,y):calc4(x,y);
        if(fl)
            write(x),putchar(' '),write(y),exit(0);
    }
    int main()
    {
        s=read();
        c=getchar();
        while(c!='A'&&c!='B')
            c=getchar();
        t=read();
        for(register int k=0,nw=c=='A';k<=t;++k,nw^=1)
            for(register int i=s;i<=N;++i)
                for(register int j=i;j<=N;++j)
                {
                    if(k>1)
                        f[i][j][k]=f[i][j][k-2];
                    f[i][j][k]|=nw?calc1(i,j,k):calc2(i,j,k);
                }
        for(register int sum=s<<1;;++sum)
            for(register int i=s;i<=sum>>1;++i)
                Work(i,sum-i);
    	return 0;
    }
    
    

    R2T2链上二次求和

    因为是一条链,所以我们可以放到区间上去看(注意:因为是链,所以修改/查询的区间有可能会出现(l>r)的情况)

    (S)为数列的前缀和,(SS)(S)的前缀和

    [sum_{i=l}^{r} sum_{j=i}^{n}left(S_{j}-S_{j-i} ight)=sum_{i=l}^{r}left(sum_{j=i}^{n} S_{j}-sum_{j=0}^{n-i} S_{j} ight)=sum_{i=l}^{r}left(S S_{n}-S S_{i-1}-S S_{n-i} ight) ]

    这个珂以用线段树维护

    对于每个修改操作,我们要考虑对SS每个位置的贡献

    • (l leq i leq r , frac{(i-l+1)(i-l+2)v}{2})

    • (r<i , (frac{(r-l+1)(r-l+2)}{2}+(i-r)(r-l+1))v)

    线段树上维护二次函数区间加即可,复杂度为(O((n+m)log n))

    #include <bits/stdc++.h>
    #define mod 1000000007
    #define N 200005
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline void add(register int &x,register int y)
    {
        x+=y;
        if(x>=mod)
            x-=mod;
    }
    const int inv2=500000004,inv6=166666668;
    int n,m;
    int a[N<<3],b[N<<3],c[N<<3],t[N<<3];
    inline int S(register int n)
    {
        return 1ll*n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
    }
    inline void put(register int x,register int l,register int r,register int A,register int B,register int C)
    {
        int s0=r-l+1,s1=1ll*(l+r)*(r-l+1)/2%mod;
        int s2=(S(r)-S(l-1)+mod)%mod;
        add(t[x],1ll*A*s2%mod);
        add(t[x],1ll*B*s1%mod);
        add(t[x],1ll*C*s0%mod);
        add(a[x],A),add(b[x],B),add(c[x],C);
    }
    inline void pushdown(register int x,register int l,register int r)
    {
        if(!(a[x]||b[x]||c[x]))
            return;
        int mid=l+r>>1;
        put(x<<1,l,mid,a[x],b[x],c[x]);
        put(x<<1|1,mid+1,r,a[x],b[x],c[x]);
        a[x]=b[x]=c[x]=0;
    }
    inline void modify(register int x,register int l,register int r,register int insl,register int insr,register int a,register int b,register int c)
    {
        if(insl<=l&&r<=insr)
        {
            put(x,l,r,a,b,c);
            return;
        }
        int mid=l+r>>1;
        pushdown(x,l,r);
        if(insl<=mid)
            modify(x<<1,l,mid,insl,insr,a,b,c);
        if(insr>mid)
            modify(x<<1|1,mid+1,r,insl,insr,a,b,c);
        t[x]=(t[x<<1]+t[x<<1|1])%mod;
    }
    inline int query(register int x,register int l,register int r,register int insl,register int insr)
    {
        if(insl<=l&&r<=insr)
            return t[x];
        pushdown(x,l,r);
        int mid=l+r>>1,res=0;
        if(insl<=mid)
            res+=query(x<<1,l,mid,insl,insr);
        if(insr>mid)
            res+=query(x<<1|1,mid+1,r,insl,insr);
        return res%mod;
    }
    int main()
    {
        n=read(),m=read();
        for(register int i=1,x,s=0,ss=0;i<=n;++i)
        {
            x=read();
            add(s,x);
            add(ss,s);
            modify(1,0,n,i,i,0,0,ss);
        }
        for(register int i=1;i<=m;++i)
        {
            int op=read();
            if(op==1)
            {
                int l=read(),r=read(),v=read();
                if(l>r)
                    l^=r^=l^=r;
                v=1ll*v*inv2%mod;
                int a=v,b=(1ll*(3-2*l)*v%mod+mod)%mod;
                int c=(1ll*v*(1ll*l*l%mod-3ll*l+2)%mod+mod)%mod;
                modify(1,0,n,l,r,a,b,c);
                a=0,b=2ll*(r-l+1)*v%mod;
                c=(1ll*(r-l+1)*(r-l+2)%mod*v%mod-1ll*r*b%mod+mod)%mod;
                if(r!=n)
                    modify(1,0,n,r+1,n,a,b,c);
            }
            else
            {
                int l=read(),r=read();
                if(l>r)
                    l^=r^=l^=r;
                int ans=1ll*query(1,0,n,n,n)*(r-l+1)%mod;
                add(ans,mod-query(1,0,n,l-1,r-1));
                add(ans,mod-query(1,0,n,n-r,n-l));
                write(ans),puts("");
            }
        }
    	return 0;
    }
    

    R2T3治疗之雨

    题意好像不太清楚,或许是我语文太差

    实际就是每轮操作随机一个不满血的加一滴血,随机(k)个减一滴血,问期望多少回合后血量会为0

    我们设(p_x)表示一次操作扣(x)滴血的概率

    [p_x= binom{k}{x} (frac{1}{m+1})^x (frac{m}{m+1})^{k-x} ]

    我们设(E_x)表示还有(i)滴血时期望多少回合后血量会为0

    对于(i in [1,n-1])

    [E_{i}=left(sum_{j=1}^{j}left(frac{m}{m+1} p_{i-j}+frac{1}{m+1} p_{i-j+1} ight) E_{j} ight)+left(frac{1}{m+1} p_{0} ight) E_{i+1}+1 ]

    对于(i=n)

    [E_{n}=left(sum_{j=1}^{n} p_{n-j} E_{j} ight)+1 ]

    进行高斯消元即可,于是我们就得到了能拿70pts的好做法

    发现这个矩阵很有特点,几乎是一个下三角矩阵,所以我们珂以用(n^2)的时间求解,总复杂度(O(Tn^2))

    #include <bits/stdc++.h>
    #define mod 1000000007
    #define N 1505
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline int power(register int a,register int b)
    {
        int res=1;
        while(b)
        {
            if(b&1)
                res=1ll*res*a%mod;
            a=1ll*a*a%mod;
            b>>=1;
        }
        return res;
    }
    int T,n,p,m,k,inv[N],P[N],F[N][N],f[N];
    inline int work()
    {
        memset(P,0,sizeof(P));
        n=read(),p=read(),m=read(),k=read();
        if(!k||(m==0&&k==1))
            return -1;
        if(m==0)
        {
            int res=0;
            for(;p>0;p-=k,++res)
                if(p<n)
                    ++p;
            return res;
        }
        int inva=power(m+1,mod-2);
        inv[1]=1;
        for(register int i=2;i<=n+1;++i)
            inv[i]=mod-1ll*mod/i*inv[mod%i]%mod;
        for(register int i=0,C=1;i<=min(n,k);C=1ll*C*inv[i+1]%mod*(k-i)%mod,++i)
            P[i]=1ll*C*power(inva,i)%mod*power(1ll*m*inva%mod,k-i)%mod;
        for(register int i=1;i<n;++i)
        {
            for(register int j=1;j<=i;++j)
                F[i][j]=(1ll*m*inva%mod*P[i-j]%mod+1ll*inva*P[i-j+1]%mod)%mod;
            F[i][i+1]=1ll*inva*P[0]%mod;
            (F[i][i]+=mod-1)%=mod;
            F[i][n+1]=mod-1;
        }
        for(register int i=1;i<=n;++i)
            F[n][i]=P[n-i];
        (F[n][n]+=mod-1)%=mod;
        F[n][n+1]=mod-1;
        for(register int i=n;i>=2;--i)
        {
            if(!F[i][i])
                return -1;
            int t=1ll*F[i-1][i]*power(F[i][i],mod-2)%mod;
            for(register int j=i;j>=1;--j)
                F[i-1][j]=(F[i-1][j]-1ll*F[i][j]*t%mod+mod)%mod;
            F[i-1][n+1]=(F[i-1][n+1]-1ll*F[i][n+1]*t%mod+mod)%mod;
        }
        for(register int i=1;i<=n;++i)
        {
            int res=F[i][n+1];
            for(register int j=1;j<i;++j)
                res=(res-1ll*f[j]*F[i][j]%mod+mod)%mod;
            f[i]=1ll*res*power(F[i][i],mod-2)%mod;
        }
        return f[p];
    }
    int main()
    {
        T=read();
        while(T--)
            write(work()),puts("");
    	return 0;
    }
    
  • 相关阅读:
    java获取本机IP和主机名
    SSH框架总结(框架分析+环境搭建+实例源代码下载)
    Centos7安装mysql8教程
    jquery 操作HTML data全局属性缓存的坑
    mysql协议分析2---认证包
    mysql协议分析1---报文的格式和基本类型
    TCP三次握手抓包理解
    java读写文件小心缓存数组
    spring 事务隔离级别导致的bug
    mysql 不同版本下 group by 组内排序的差异
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/11329732.html
Copyright © 2011-2022 走看看