睿频阿百川

ABC304G

说实话真不敢往那方面想

显然二分,然后我们就把数全部打到\(Tire\)树上

尝试让\(a_x\oplus a_y\ge mid\)匹配数量多,如果对于节点\(u\),\(mid\)深度为\(0\)则直接左右匹配再往重的那边子树走,如果为\(1\)就必须考虑两边子树,这看着不好做

实际上就算是递归两边子树也可做,因为不会产生更多的分叉,这个分讨一下即可

Show Code
// LUOGU_RID: 126326885
#include<bits/stdc++.h>//
using namespace std;
const int MAXN=2e5+5;///
int Tree[MAXN*30][2];
int cnt_node;
int Num[MAXN*30];
int n;
int a[MAXN];
void Insert(int x)
{//
    int p=0;
    for(int i=30;i>=0;i--)
    {
        int op=(x>>i)&1;
        if(!Tree[p][op])
        {
            Tree[p][op]=++cnt_node;
        }
        p=Tree[p][op];
        Num[p]++;
    }
}
int Lit;
int dfs(int u1,int u2,int dep)
{
    if(dep==-1)
    {
        if(u1==u2)
        {
            return 0;
        }
        else
        {
            return min(Num[u1],Num[u2]);
        }
    }
    if((!u1)&&(dep!=30))
    {
        return 0;
    }
    if((!u2)&&(dep!=30))
    {
        return 0;
    }

    if(u1==u2)
    {
        if((Lit>>dep)&1)
        {
            return dfs(Tree[u1][0],Tree[u1][1],dep-1);
        }
        else
        {
            if(Num[Tree[u1][0]]>Num[Tree[u1][1]])
            {
                return Num[Tree[u1][1]]+min((Num[Tree[u1][0]]-Num[Tree[u1][1]])/2,dfs(Tree[u1][0],Tree[u1][0],dep-1));
            }
            else
            {
                return Num[Tree[u1][0]]+min((Num[Tree[u1][1]]-Num[Tree[u1][0]])/2,dfs(Tree[u1][1],Tree[u1][1],dep-1));
            }
        }
    }
    else
    {
        if((Lit>>dep)&1)
        {
            return dfs(Tree[u1][0],Tree[u2][1],dep-1)+dfs(Tree[u1][1],Tree[u2][0],dep-1);
        }
        else
        {
            if(Num[Tree[u1][0]]>Num[Tree[u2][1]]&&Num[Tree[u1][1]]<Num[Tree[u2][0]])
            {
                return Num[Tree[u2][1]]+Num[Tree[u1][1]]+min(min((Num[Tree[u1][0]]-Num[Tree[u2][1]]),(Num[Tree[u2][0]]-Num[Tree[u1][1]])),dfs(Tree[u1][0],Tree[u2][0],dep-1));
            }
            else if(Num[Tree[u1][0]]<Num[Tree[u2][1]]&&Num[Tree[u1][1]]>Num[Tree[u2][0]])
            {
                return Num[Tree[u2][0]]+Num[Tree[u1][0]]+min(min((Num[Tree[u1][1]]-Num[Tree[u2][0]]),(Num[Tree[u2][1]]-Num[Tree[u1][0]])),dfs(Tree[u1][1],Tree[u2][1],dep-1));
            }
            else 
            {
                return min(Num[Tree[u1][0]],Num[Tree[u2][1]])+min(Num[Tree[u1][1]],Num[Tree[u2][0]]);
            }
        }
    }
}
bool check(int mid)
{
    Lit=mid;
   // printf("%d??\n",dfs(0,0,30));
    return dfs(0,0,30)>=(n+1)/2;
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=2*n;i++)
    {
        scanf("%d",&a[i]);
        Insert(a[i]);
    }
    int l=1;////
    int r=(1<<30);
    int Key=0;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid))
        {
            Key=mid;
            l=mid+1;
        }
        else
        {
            r=mid-1;
        }
    }
    printf("%d\n",Key);
}

ABC290G

直接枚举往上割的子树然后在从大到小枚举深度割向下的边即可

感觉这个构造类似与\(k\)进制拆分

Show Code
#include<bits/stdc++.h>
using namespace std;
int T;
long long D,K;
long long X;
long long Siz[105];
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld %lld %lld",&D,&K,&X);
        long long Res=2e18;
        for(int i=0;i<=D;i++)
        {
            __int128 Ne=1;
            for(int j=1;j<=i+1;j++)
            {
                Ne*=K;
            }
            Ne=Ne-1;
            Ne=(Ne/(K-1));
            Siz[i]=Ne;
        }

        for(int i=0;i<=D;i++)
        {
            long long Now=Siz[i];
            long long tot=1;
            if(i==D)
            {
                tot--;
            }
            long long Det=Now-X;
            if(Det<0)
            {
                continue;
            }
            for(int j=i-1;j>=0;j--)
            {
                tot+=(Det/Siz[j]);
                Det%=Siz[j];
            }
            if(Det==0)
            {
                Res=min(Res,tot);
            }
        }
        printf("%lld\n",Res);
    }
}   

ABC290Ex

神秘题

不难发现我们尽量让最大的放中间

如果\(n,m\)不为偶数的话我们一定得把大的放中间

如果均为偶数,实际上我们左右两边猫狗数量应该相同,因为如果不同一定可以通过调整使得答案更有

实际上两侧同样满足递增得性质,我们据此\(dp\)即可

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=305;
int n,m;
int a[MAXN];
int b[MAXN];
long long dp[MAXN*2][MAXN][MAXN];
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&b[i]);
    }
    sort(a+1,a+1+n);
    sort(b+1,b+1+m);
    long long Res=0;
    if(n&1)
    {
        if(m&1)
        {
            Res+=a[n];
        }
        for(int i=1;i<=m;i++)
        {
            Res+=b[i];
        }
        n--;
    }

    if(m&1)
    {
        for(int i=1;i<=n;i++)
        {
            Res+=a[i];
        }
        m--;
    }

    vector<pair<int,int> >V;
    V.push_back(make_pair(0,0));
    for(int i=1;i<=n;i++)
    {
        V.push_back(make_pair(a[i],0));
    }
    for(int i=1;i<=m;i++)
    {
        V.push_back(make_pair(b[i],1));
    }

    sort(V.begin(),V.end());
    memset(dp,0x3f,sizeof(dp));
    dp[0][0][0]=0;
    int s0=0;
    int s1=0;
    for(int i=0;i<n+m;i++)
    {
        for(int j=0;j<=min(s0,n/2);j++)
        {
            for(int k=0;k<=min(s1,m/2);k++)
            {
                if(V[i+1].second==0)
                {
                    int qj=(s0-j);
                    int qk=(s1-k);
                    if(qj<=n/2&&qk<=m/2)
                    {
                        dp[i+1][j][k]=min(dp[i+1][j][k],dp[i][j][k]+((long long)V[i+1].first*(m-2*qk)));
                        dp[i+1][j+1][k]=min(dp[i+1][j+1][k],dp[i][j][k]+((long long)V[i+1].first*(m-2*k)));
                    }
                }
                else
                {
                    int qj=(s0-j);
                    int qk=(s1-k);
                    if(qj<=n/2&&qk<=m/2)
                    {
                        dp[i+1][j][k]=min(dp[i+1][j][k],dp[i][j][k]+((long long)V[i+1].first*(n-2*qj)));
                        dp[i+1][j][k+1]=min(dp[i+1][j][k+1],dp[i][j][k]+((long long)V[i+1].first*(n-2*j)));
                    }
                    
                }
            }
        }
        if(V[i+1].second==0)
        {
            s0++;
        }
        else
        {
            s1++;
        }
    }
    printf("%lld\n",Res+dp[n+m][n/2][m/2]);
}   

ABC289G

一眼决策单调性

好吧,证明也很显,不过这里我们决策点得是\(B\)中的数,当然这样不劣

用一下分治即可

Show Code
#include<bits/stdc++.h>
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;
const int MAXN=2e5+5;
int n,m;
int x;
pair<int,int>C[MAXN];
int B[MAXN];
long long Ans[MAXN];
long long Cal(int x,int c)
{
    int Ce=n-(lower_bound(B+1,B+1+n,c-C[x].first)-B)+1;
    return ((long long)Ce*c);
}
void solve(int ql,int qr,int l,int r)
{
    if(ql>qr)
    {
        return;
    }
    if(l==r)
    {
        for(int i=ql;i<=qr;i++)
        {
            Ans[C[i].second]=Cal(i,B[l]+C[i].first);
        }
        return;
    }

    int mid=(ql+qr)>>1;
    long long Maxi=0;
    int Key;
    for(int i=l;i<=r;i++)
    {
        if(Cal(mid,B[i]+C[mid].first)>=Maxi)
        {
            Maxi=Cal(mid,B[i]+C[mid].first);
            Key=i;
        }
    }
    Ans[C[mid].second]=Maxi;
    solve(ql,mid-1,Key,r);
    solve(mid+1,qr,l,Key);
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&B[i]);
    }
    sort(B+1,B+1+n);
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&C[i].first);
        C[i].second=i;
    }
    sort(C+1,C+1+m);
    solve(1,m,1,n);
    for(int i=1;i<=m;i++)
    {
        printf("%lld ",Ans[i]);
    }
}       

ABC288G

第一眼以为是找规律

结果这\(A,B\)之间是个线性变换,也确实是,类似于高维前缀和,直接求出逆即可

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=6e5+5;
int n;
int Pw[15];
int a[MAXN]; 
int b[MAXN];
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    Pw[0]=1;
    for(int i=1;i<=n;i++)
    {
        Pw[i]=Pw[i-1]*3;
    }
    //cerr<<Pw[n]<<endl;
    for(int i=0;i<Pw[n];i++)
    {
        scanf("%d",&a[i]);
    }
    
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<Pw[n];j++)
        {
            b[j]=a[j];
            a[j]=0;
        }
        for(int j=0;j<Pw[n];j++)
        {
            int op=(j/Pw[i])%3;
            int ept=(j-op*Pw[i]);
            if(op==1)
            {
                a[j]=b[ept]+b[ept+Pw[i]*2]-b[ept+Pw[i]];
            }
            else if(op==2)
            {
                a[j]=b[ept+Pw[i]]-b[ept];
            }
            else
            {
                a[j]=b[ept+Pw[i]]-b[ept+2*Pw[i]];
            }
        }
    }

    for(int i=0;i<Pw[n];i++)
    {
        printf("%d ",a[i]);
    }
}   

ABC287G

直接权值线段树即可

Show Code
#include<bits/stdc++.h>
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;

const int MAXN=2e6+5;
int n,q;
int op;
int x,y;
int a[MAXN];
int b[MAXN];
struct Seg{
    int lc,rc;
    int num;
    long long date;
}Tree[MAXN*10];
int cnt_node;
int rt;
void Insert(int &p,int l,int r,int k,int x)
{
    if(!p)
    {
        p=++cnt_node;
        Tree[p].lc=Tree[p].rc=Tree[p].num=Tree[p].date=0;
    }
    Tree[p].num+=x;
    Tree[p].date+=(long long)x*k;
    if(l==r)
    {
        return;
    }
    int mid=(l+r)>>1;
    if(k<=mid)
    {
        Insert(ls,l,mid,k,x);
    }
    else
    {
        Insert(rs,mid+1,r,k,x);
    }
}
long long Query(int p,int l,int r,int k)
{
    if(!p)
    {
        return 0;
    }
    if(l==r)
    {
        return (long long)k*l;
    }
    int mid=(l+r)>>1;
   // printf("%d %d %d %d %d:::\n",l,r,k,Tree[rs].num,Tree[p].num);
    if(Tree[rs].num<=k)
    {
        return Tree[rs].date+Query(ls,l,mid,k-Tree[rs].num);
    }
    else
    {
        return Query(rs,mid+1,r,k);
    }
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d %d",&a[i],&b[i]);
        Insert(rt,0,1e9,a[i],b[i]);
    }
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d %d",&x,&y);
            Insert(rt,0,1e9,a[x],-b[x]);
            a[x]=y;
            Insert(rt,0,1e9,a[x],b[x]);
        }
        else if(op==2)
        {
            scanf("%d %d",&x,&y);
            Insert(rt,0,1e9,a[x],-b[x]);
            b[x]=y;
            Insert(rt,0,1e9,a[x],b[x]);
        }
        else if(op==3)
        {
            scanf("%d",&x);
            if(Tree[rt].num<x)
            {
                printf("-1\n");
            }
            else
            {
                printf("%lld\n",Query(rt,0,1e9,x));
            }
        }
    }
}   

ABC288Ex

什么狗霸体

最开始的思路记不到了,反正直接数位\(dp\)搞一下,不过有点难限制

正解的话先不考虑重复元素,这里数位\(dp\)搞一下没啥问题,然后考虑枚举\((i,j,k)\)表示有\(i\)个位置是出现次数为奇数的元素,有\(j\)个奇数次数的元素,有\(k\)个偶数次数的元素,这样的方案减一下刚好不重不漏得到没有重复元素的答案,最后再消消序即可

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=205;
int fac[MAXN];
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int n,m,x;
int g[MAXN];
int dp[35][MAXN];
int C[MAXN][MAXN];
int Even[MAXN][MAXN];
int Odd[MAXN][MAXN];
int Reg[MAXN][MAXN];
int c(int n,int m)
{
    int rt=1;
    for(int i=n-m+1;i<=n;i++)
    {
        rt=((long long)rt*i)%MOD;
    }
    int pt=1;
    for(int i=1;i<=m;i++)
    {
        pt=((long long)pt*i)%MOD;
    }
    rt=((long long)rt*inv(pt,MOD))%MOD;
    return rt;
}
int main()
{   
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    C[0][0]=1;
    fac[0]=1;
    for(int i=1;i<=MAXN-5;i++)
    {
        C[i][0]=1;
        fac[i]=((long long)fac[i-1]*i)%MOD;
        for(int j=1;j<=MAXN-5;j++)
        {
            C[i][j]=((long long)C[i-1][j]+C[i-1][j-1])%MOD;
        }
    }
    scanf("%d %d %d",&n,&m,&x);
    for(int l=1;l<=n;l++)
    {
        memset(dp,0,sizeof(dp));
        dp[31][0]=1;
        for(int i=30;i>=0;i--)
        {
            for(int j=0;j<=l;j++)
            {
                int Od=0,Ev=0;
                for(int k=0;k<=j;k++)
                {
                    if(k&1)
                    {
                        Od=((long long)Od+C[j][k])%MOD;
                    }
                    else
                    {
                        Ev=((long long)Ev+C[j][k])%MOD;
                    }
                }
                if((m>>i)&1)
                {
                    for(int k=0;k+j<=l;k++)
                    {
                        int Ry=(l-k-j);
                        int Rtu=(Ry&1)^((x>>i)&1);
                        int Rst=1;
                        if(Rtu&1)
                        {
                            Rst=((long long)Rst*Od)%MOD;
                        }
                        else
                        {
                            Rst=((long long)Rst*Ev)%MOD;
                        }
                        Rst=((long long)Rst*C[l-j][k])%MOD;
                        dp[i][j+k]=((long long)dp[i][j+k]+((long long)dp[i+1][j]*Rst)%MOD)%MOD;
                    }
                }
                else
                {
                    int Rtu=(x>>i)&1;
                    int Rst=1;
                    if(Rtu&1)
                    {
                        Rst=((long long)Rst*Od)%MOD;
                    }
                    else
                    {
                        Rst=((long long)Rst*Ev)%MOD;
                    }
                    dp[i][j]=((long long)dp[i][j]+((long long)dp[i+1][j]*Rst)%MOD)%MOD;
                }
                
            }
        }
        g[l]=0;
        for(int i=0;i<=l;i++)
        {
            g[l]=((long long)g[l]+dp[0][i])%MOD;
        }
    }
    Odd[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            for(int k=1;k<=i;k+=2)
            {
                Odd[i][j]=((long long)Odd[i][j]+((long long)Odd[i-k][j-1]*C[i][k])%MOD)%MOD;
            }
        }
    }

    Even[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            for(int k=2;k<=i;k+=2)
            {
                Even[i][j]=((long long)Even[i][j]+((long long)Even[i-k][j-1]*C[i][k])%MOD)%MOD;
            }
        }
    }

    
    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<=i;j++)
        {
            Even[i][j]=((long long)Even[i][j]*inv(fac[j],MOD))%MOD;
            Odd[i][j]=((long long)Odd[i][j]*inv(fac[j],MOD))%MOD;
        //    printf("%d %d:\n",i,j);
        //    printf("%d\n%d\n",Even[i][j],Odd[i][j]);
        }
    }
    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            int Mul=1;
            int Ptto=m-j+1;

            for(int k=0;k<=n;k++)
            {
                int Wto=0;
                Wto=Even[i][k];
                Wto=((long long)Wto*Mul)%MOD;
                Reg[i][j]=((long long)Reg[i][j]+Wto)%MOD;

                Mul=((long long)Mul*Ptto)%MOD;
                Ptto--;
                if(Ptto<0)
                {
                    break;
                }
            }
            //printf("%d %d %d--\n",i,j,Reg[i][j]);
        }
    }

    if(x==0)
    {
        g[0]=1;
        //cerr<<"fic"<<endl;
    }
    for(int l=1;l<=n;l++)
    {
        for(int i=0;i<=l;i++)
        {
            for(int j=0;j<l;j++)
            {
                int Vto=((long long)C[l][i]*Odd[i][j])%MOD;
                Vto=((long long)Vto*g[j])%MOD;
                Vto=((long long)Vto*Reg[l-i][j])%MOD;
                g[l]=((long long)g[l]-Vto+MOD)%MOD;
            }
        }
    }
    // cerr<<g[0]<<endl;
    // for(int i=0;i<=n;i++)
    // {
    //     printf("%d:: %d\n",i,g[i]);
    // }
    int Res=0;
    for(int i=n;i>=0;i-=2)
    {
        int Tto=g[i];
        Tto=((long long)Tto*c(m+(n-i)/2,(n-i)/2))%MOD;
        Tto=((long long)Tto*inv(fac[i],MOD))%MOD;
        Res=((long long)Res+Tto)%MOD;
    }
    printf("%d\n",Res);



}

ABC321G

狗霸体+1

不难发现\(a-b|x\),如果\(k=2\),直接可以算

如果\(k\ge3\),不难发现\(a^2-b^2\le x\),枚举\(a+b\),这样时间复杂度是因数和也不是很大

枚举完暴力跑背包即可,卡卡常

正解似乎不用背包,直接进制填即可

Show Code
#include<bits/stdc++.h>
using namespace std;//
const int MOD=998244353;
int n,x;
int Res=0;
map<int,int>Vis,Tmp;
void work(int d)
{
    int rkt=(x/d);
    int Use=Res;
    if(rkt<10)
    {
        int Zptr=n-d;
        int Zptl=rkt+1;
        if(Zptl<=Zptr)
        {
            int Ztll=max(10,Zptl);
            if(Ztll<=Zptr)
            {
                Res=((long long)Res+(10ll*(Zptr-Ztll+1))%MOD)%MOD;
            }
            

            for(int b=Zptl;b<=min(9,Zptr);b++)
            {
                Res=((long long)Res+b)%MOD;
            }
        }
    }
    //printf("%d %d::\n",d,Res-Use);
    for(int sp=d+2;sp<=x/d;sp+=2)
    {
        int a=(d+sp)/2;
        int b=(a-d);
        if(a>n)
        {
            continue;
        }
        long long Ma=1;
        long long Mb=1;
        int k;
        for(k=1;;k++)
        {
            Ma=Ma*a;
            Mb=Mb*b;
            if(Ma-Mb>x)
            {
                k--;
                break;
            }
        }

        for(int len=k;len>=1;len--)
        {
            
            Vis.clear();
            long long Na=Ma;
            long long Nb=Mb;
            Vis[0]=1;
            for(int i=len;i>=1;i--)
            {
                Na/=a;
                Nb/=b;
                Tmp.clear();
                for(int j=(i==len);j<min(10,b);j++)
                {
                    for(auto it=Vis.begin();it!=Vis.end();it++)
                    {
                        pair<int,int>Tty=(*it);
                        int Nro=(Tty.first+(Na-Nb)*j);
                        if(Nro>x)
                        {
                            continue;
                        }
                        Tmp[Nro]=((long long)Tmp[Nro]+Tty.second)%MOD;
                    }
                }
                Vis=Tmp;
            }
            Ma/=a;
            Mb/=b;
            Res=((long long)Res+((long long)Vis[x]*min(b,10))%MOD)%MOD;
        }
    }   
    
}
signed main()
{   
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&x);
    for(int d=1;d*d<=x;d++)
    {
        if(x%d==0)
        {
            work(d);
            if(d*d!=x)
            {
                work(x/d);
            }
        }
    }
    printf("%d\n",Res);
    //cerr<<(clock()*1.0/CLOCKS_PER_SEC)<<endl;
}

ABC287Ex

直接bitset优化floyd即可

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2005;
const int MAXQ=1e4+5;
int n,m,q;
int x,y;
pair<int,int> Q[MAXQ];
int Ans[MAXQ];
bitset<MAXN>S[MAXN];
int main()
{   
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&x,&y);
        S[x].set(y);
    
    }
    for(int i=1;i<=n;i++)
    {
        S[i].set(i);
    }
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%d %d",&x,&y);
        Q[i]=make_pair(x,y);
        Ans[i]=-1;
        if(S[Q[i].first][Q[i].second])
        {
            Ans[i]=0;
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(S[j][i])
            {
                S[j]|=S[i];
            }
        }

        for(int j=1;j<=q;j++)
        {
            if(Ans[j]==-1)
            {
                if(S[Q[j].first][Q[j].second])
                {
                    Ans[j]=i;
                }
            }
        }
    }

    for(int i=1;i<=q;i++)
    {
        printf("%d\n",max(Ans[i],max(Q[i].first,Q[i].second)));
    }
}

ABC286G

直接对非关键边缩点之后判欧拉回路即可

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
struct Edge{
    int u,v;
}edge[MAXN];
int n,m,x,y;
int fa[MAXN];
int vis[MAXN];
int k;
int find(int x)
{
    if(fa[x]==x)
    {
        return x;
    }
    fa[x]=find(fa[x]);
    return fa[x];
}
void unionn(int i,int j)
{
    fa[find(i)]=find(j);
}
int d[MAXN];
int main()
{   
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&x,&y);
        edge[i]=((Edge){x,y});
    }
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
    }
    scanf("%d",&k);
    for(int i=1;i<=k;i++)
    {
        scanf("%d",&x);
        vis[x]=1;
    }
    for(int i=1;i<=m;i++)
    {
        if(!vis[i])
        {
            unionn(edge[i].u,edge[i].v);
        }
    }
    for(int i=1;i<=m;i++)
    {
        if(vis[i])
        {
            d[find(edge[i].u)]++;
            d[find(edge[i].v)]++;
        }
    }   
    int Cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(d[i]&1)
        {
            ++Cnt;
        }
    }
    if(Cnt==0||Cnt==2)
    {
        printf("Yes");
    }
    else{
        printf("No");
    }
}

ABC266G

傻瓜容斥(话说这种题我之前为啥没做出来

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=4e6+5;
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int inv_fac[MAXN];
int fac[MAXN];
int C(int n,int m)
{
    if(n<m||m<0)
    {
        return 0;
    }
    if(n==m||m==0)
    {
        return 1;
    }
    return ((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD;
}

int k,R,G,B;
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    fac[0]=1;
    for(int i=1;i<=MAXN-5;i++)
    {
        fac[i]=((long long)fac[i-1]*i)%MOD;
    }
    inv_fac[MAXN-5]=inv(fac[MAXN-5],MOD);
    for(int i=MAXN-5-1;i>=1;i--)
    {
        inv_fac[i]=((long long)inv_fac[i+1]*(i+1))%MOD;
    }
    
    scanf("%d %d %d %d",&R,&G,&B,&k);
    int Res=0;
    int n=R+G+B;
    for(int i=k;i<=min(R,G);i++)
    {
        int val=C(n-i,i);
        val=((long long)val*C(n-2*i,B))%MOD;
        val=((long long)val*C(n-2*i-B,R-i))%MOD;
        val=((long long)val*C(n-2*i-B-(R-i),G-i))%MOD;
        val=((long long)val*C(i,k))%MOD;
        if((i-k)&1)
        {
            Res=((long long)Res-val+MOD)%MOD;
        }
        else
        {
            Res=((long long)Res+val)%MOD;
        }
    }
    printf("%d\n",Res);
}

ABC286Ex

不难想到最短路,连边要求不穿过凸包

实际上这个判断条件就是看凸包,不如直接在凸包上走

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+5;
struct node{
    double x,y;
    node(double xx=0,double yy=0){
        x=xx;
        y=yy;
        return;
    }
    node operator+(const node a)const{
        return ((node){x+a.x,y+a.y});
    }
    node operator-(const node a)const{
        return ((node){x-a.x,y-a.y});
    }
};
double dist(node a,node b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmpx(node a,node b)
{
    if(a.x==b.x)
    {
        return a.y<b.y;
    }
    return a.x<b.x;
}
double cross(node a,node b)
{
    return a.x*b.y-a.y*b.x;
}
int st[MAXN];
int head=0;
int Used[MAXN];
vector<node> Convex(vector<node>P)
{
    for(int i=0;i<P.size();i++)
    {
        Used[i]=0;
    }
    sort(P.begin(),P.end(),cmpx);
    head=0;
    st[++head]=0;
    for(int i=1;i<P.size();i++)
    {
        while(head>=2&&cross(P[st[head]]-P[st[head-1]],P[i]-P[st[head]])<=0)
        {
            Used[st[head]]=0;
            head--;
        }
        st[++head]=i;
        Used[i]=1;
    }   
    int Mp=head;
    for(int i=P.size()-1;i>=0;i--)
    {
        if(Used[i])
        {
            continue;
        }
        while(head>Mp&&cross(P[st[head]]-P[st[head-1]],P[i]-P[st[head]])<=0)
        {
            Used[st[head]]=0;
            head--;
        }
        st[++head]=i;
        Used[i]=1;
    }
    vector<node>R;
    R.clear();
    for(int i=1;i<head;i++)
    {
        R.push_back(P[st[i]]);
    }
    return R;
}
vector<node>V;
int n;
double x,y;
int main()
{  
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf %lf",&x,&y);
        V.push_back((node){x,y});
    }

    double sx,sy,tx,ty;
    scanf("%lf %lf",&x,&y);
    V.push_back((node){x,y});
    sx=x;
    sy=y;
    scanf("%lf %lf",&x,&y);
    V.push_back((node){x,y});
    tx=x;
    ty=y;
    V=Convex(V);
    int s=-1,t=-1;
    for(int i=0;i<V.size();i++)
    {
        if(V[i].x==sx&&V[i].y==sy)
        {
            s=i;
        }
        if(V[i].x==tx&&V[i].y==ty)
        {
            t=i;
        }
    }
    if(s==-1||t==-1)
    {
        printf("%lf",dist((node){sx,sy},(node){tx,ty}));
        return 0;
    }
    double Res=2e18;
    if(s>t)
    {
        swap(s,t);
    }
    double Tot=0;
    for(int i=s;i<t;i++)
    {
        Tot+=dist(V[i],V[i+1]);
    }
    Res=Tot;
    Tot=0;
    for(int i=t;i<V.size()-1;i++)
    {
        Tot+=dist(V[i],V[i+1]);
    }
    Tot+=dist(V.back(),V[0]);
    for(int i=0;i<s;i++)
    {
        Tot+=dist(V[i],V[i+1]);
    }
    Res=min(Res,Tot);
    printf("%.9lf",Res);

}

ABC285G

把网格图抽象为二分图后不难看出上下界网络流

Show Code
#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
const int MAXN=305*305;
const int MAXM=305*305*4;
struct Edge{
	int to,val,nex;
}edge[MAXM*4];
int cnt_edge=1;
int head[MAXN];
int arc[MAXN];
int dis[MAXN];

void Add(int u,int v,int val)
{
	edge[++cnt_edge].nex=head[u];
	edge[cnt_edge].to=v;
	edge[cnt_edge].val=val;
	head[u]=cnt_edge;
}
void add(int u,int v,int val)
{
    Add(u,v,val);
    Add(v,u,0);
    return;
}
int s,t;
int bfs()
{
	memset(dis,-1,sizeof(dis));
	dis[s]=0;
	queue<int>q;
	q.push(s);
	arc[s]=head[s];
	while(q.size())
	{
		int temp=q.front();
		q.pop();
		for(int i=head[temp];i;i=edge[i].nex)
		{
			int v=edge[i].to;
			int w=edge[i].val;
			if(w>0&&dis[v]==-1)
			{
				arc[v]=head[v];
				dis[v]=dis[temp]+1;
				q.push(v);
			}
		}
	}
	return (dis[t]==-1)?0:1;
}
int dfs(int x,int Lit)
{
	if(x==t)
	{
		return Lit;
	}
	int used=0;
	int rest=Lit;
	for(int i=arc[x];i;i=edge[i].nex)
	{
		arc[x]=i;
		int v=edge[i].to;
		int w=edge[i].val;
		if(dis[v]==dis[x]+1&&w>0)
		{
			int Nowx=dfs(v,min(w,rest));
			if(!Nowx)
			{
				continue;
			}
			used+=Nowx;
			rest-=Nowx;
			edge[i].val-=Nowx;
			edge[i^1].val+=Nowx;
			if(used==Lit)
			{
				break;
			}
		}
	}
	return used;
}
int dinic()
{
	int Maxflow=0;
	while(bfs())
	{
		int flow;
		while((flow=dfs(s,INF)))
		{
			Maxflow+=flow;
		}
	}	
	return Maxflow;
}
int n,m;
char mp[305][305];
vector<pair<int,pair<int,int> > >g[MAXN];
int M[MAXN];
int zfx[4]={0,0,1,-1};
int zfy[4]={1,-1,0,0};
signed main()
{
	// freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",mp[i]+1);
    }
    int S=0;
    int T=(n*m+1);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if((i+j)%2==0)
            {
                if(mp[i][j]=='2')
                {
                    g[S].push_back(make_pair((i-1)*m+j,make_pair(1,1)));
                }  
                else if(mp[i][j]=='?')
                {
                    g[S].push_back(make_pair((i-1)*m+j,make_pair(0,1)));
                }
                for(int k=0;k<4;k++)
                {
                    int nx=i+zfx[k];
                    int ny=j+zfy[k];
                    if(nx>=1&&ny>=1&&nx<=n&&ny<=m)
                    {
                        if(mp[nx][ny]=='?'||mp[nx][ny]=='2')
                        {
                            g[(i-1)*m+j].push_back(make_pair((nx-1)*m+ny,make_pair(0,1)));
                        }
                    }
                }
            }
            else
            {
                if(mp[i][j]=='2')
                {
                    g[(i-1)*m+j].push_back(make_pair(T,make_pair(1,1)));
                }  
                else if(mp[i][j]=='?')
                {
                    g[(i-1)*m+j].push_back(make_pair(T,make_pair(0,1)));
                }
            }
        }
    }
    s=n*m+2;
    t=n*m+3;
    for(int i=0;i<=n*m+1;i++)
    {
        for(int j=0;j<g[i].size();j++)
        {
            int v=g[i][j].first;
            int L=g[i][j].second.first;
            int R=g[i][j].second.second;
            M[v]+=L;
            M[i]-=L;
            add(i,v,R-L);
        }
    }
    int Tot=0;
    add(T,S,INF);
    for(int i=0;i<=n*m+1;i++)
    {
        if(M[i]>0)
        {
            Tot+=M[i];
            add(s,i,M[i]);
        }
        else if(M[i]<0)
        {
            add(i,t,-M[i]);
        }
    }
    
    //printf("%d %d\n",Tot,dinic());
    if(Tot==dinic())
    {
        printf("Yes");
    }
    else
    {
        printf("No");
    }
}

ABC284G

呕心的推狮子

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
int n,M;
int f[MAXN];
int P[MAXN];
int A(int n,int m)
{
    if(m>n)
    {
        return 0;
    }
    int Res=1;
    for(int i=n-m+1;i<=n;i++)
    {
        Res=((long long)Res*i)%M;
    }
    return Res;
}
signed main()
{
	// freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&M);
    P[0]=1;
    for(int i=1;i<=n;i++)
    {
        P[i]=((long long)P[i-1]*n)%M;
    }
    f[n]=0;
    for(int i=n;i>=2;i--)
    {
        int Val=1;
        Val=((long long)Val*P[n-i])%M;
        Val=((long long)Val+(((long long)n-i)*f[i])%M)%M;
        f[i-1]=Val;
    }
    int C=1;
    int Res=0;
    for(int i=1;i<n;i++)
    {
        C=((long long)C*(n-i))%M;
        int V=((long long)C*i)%M;
        V=((long)V*f[i])%M;
        Res=((long long)Res+V)%M;
    }   
    Res=((long long)Res*n)%M;
    printf("%d\n",Res);
    // Res=0;
    // for(int d=1;d<n;d++)
    // {
    //     int t=0;
    //     for(int s=1;s<=n;s++)
    //     {
    //         if(n-d-s>=0)
    //         {
    //             t=((long long)t+((long long)P[n-d-s]*A(n-d-1,s-1))%M)%M;
    //         }
            
    //     }
    //     t=((long long)t*d)%M;
    //     t=((long long)t*A(n-1,d))%M;
    //     Res=((long long)Res+t)%M;
    // }
    // Res=((long long)Res*n)%M;
    // printf("%d\n",Res);
    
}

ABC257G

zz KMP 没啥好说得

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e5+5;
string s,t;
int nxt[MAXN];
int Cop[MAXN];
signed main()
{
	// freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    cin>>s;
    cin>>t;
    nxt[0]=-1;
    int i=0;
    int j=-1;
    while(i<s.size())
    {
        if(j==-1||(s[i]==s[j]))
        {
            i++;
            j++;
            nxt[i]=j;
        }
        else
        {
            j=nxt[j];
        }
    }
    // cerr<<"fuck"<<endl;
    i=0;
    j=0;
    while(i<t.size())
    {
        if(j==-1||(t[i]==s[j]))
        {
            i++;
            j++;
            //printf("%d %d\n",i,j);
            Cop[i]=j;
            if(j==s.size())
            {
                j=nxt[j];
            }
        }
        else
        {
            j=nxt[j];
        }
    }

    int Now=t.size();
    int Res=0;
    while(Now>=1)
    {
        Res++;
        int Len=Cop[Now];
        if(Len==0||Len==-1)
        {
            printf("-1");
            return 0;
        }
        Now-=Len;
    }
    if(Now!=0)
    {
        printf("-1");
    }
    else
    {
        printf("%d\n",Res);
    }
}

ABC283G

线性基半屉

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
long long l,r;
int n;
long long a[MAXN];
long long B[61];
int zero;
void Insert(long long x)
{
    for(int i=60;i>=0;i--)
    {
        if((x>>i)&1)
        {
            if(B[i])
            {
                x^=B[i];
            }
            else
            {
                B[i]=x;
                break;
            }
        }
    }
    if(!x)
    {
        zero=1;
    }
}
long long Reuse[65];
long long d[65];
int cnt=0;

void rebuild()
{
	for(int i=60;i>=0;i--)
	{
		d[i]=B[i];
	}
	cnt=0;
	for(int i=60;i>=0;i--)
	{
		for(int j=i-1;j>=0;j--)
		{
			if((d[i]>>j)&1)
			{
				d[i]^=d[j];
			}
		}
	}
	for(int i=0;i<=60;i++)
	{
		if(d[i])
		{
		  //  printf("%d %lld\n",i,d[i]);
			Reuse[++cnt]=d[i];
		}
	}

	return;
}
long long Query_rank(long long x)
{
	rebuild();
	long long Res=0;
	for(int i=cnt;i>=1;i--)//高位先筛 
	{
		if(x>=Reuse[i])//不会出现1000被0100筛的情况 
		{
			Res+=(1<<((i-1)));
		//
			x^=Reuse[i]; 
		}
	} 
	return Res;
}
long long Query_rankval(int k)
{
	
	if(1)
	{
		k-=1;
	}
	if(k>=(1ll<<(cnt)))
	{
		return -1;
	}
	long long Res=0; 
	for(int i=60;i>=0;i--)
	{
		if((k>>i)&1ll)
		{	
			Res^=(Reuse[i+1]);
		}
	}
	return Res;
}
int main()
{   
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %lld %lld",&n,&l,&r);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        Insert(a[i]);
    }
    rebuild();
    for(long long i=l;i<=r;i++)
    {
        printf("%lld ",Query_rankval(i));
    }
}

ABC324G

主席树板子

Show Code
#include<bits/stdc++.h>
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;
const int MAXN=2e5+5;
struct Seg{
    int date;
    int lc,rc;
}Tree[MAXN*40];
int rt[MAXN];
int cnt_node;
int copy(int p)
{
    Tree[++cnt_node]=Tree[p];
    return cnt_node;
}
void Insert(int &p,int o,int l,int r,int k,int x)
{
    p=copy(o);
    Tree[p].date+=x;
    if(l==r)
    {
        return;
    }
    int mid=(l+r)>>1;
    if(k<=mid)
    {
        Insert(ls,Tree[o].lc,l,mid,k,x);
    }
    else
    {
        Insert(rs,Tree[o].rc,mid+1,r,k,x);
    }
}
int Query(int p,int l,int r,int ql,int qr)
{
    if(l>r)
    {
        return 0;
    }
    if(l>=ql&&r<=qr)
    {
        return Tree[p].date;
    }
    int mid=(l+r)>>1;
    int Res=0;
    if(ql<=mid)
    {
        Res+=Query(ls,l,mid,ql,qr);
    }
    if(qr>mid)
    {
        Res+=Query(rs,mid+1,r,ql,qr);
    }
    return Res;
}
int n;
int a[MAXN];
int q;
struct node{
    int l,r,lv,rv;
}s[MAXN];
int op,x,y;
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        Insert(rt[i],rt[i-1],1,n,a[i],1);
    }
    s[0]=((node){1,n,1,n});
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%d %d %d",&op,&x,&y);
        if(op==1)
        {
            if(s[x].l==-1)
            {
                s[i].l=-1;
                printf("%d\n",0);
                continue;
            }
            int l=s[x].l;
            int r=s[x].r;
            int Key=-1;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(Query(rt[mid],1,n,s[x].lv,s[x].rv)-Query(rt[s[x].l-1],1,n,s[x].lv,s[x].rv)<=y)
                {
                    l=mid+1;
                    Key=mid;
                }
                else
                {
                    r=mid-1;
                }
            }
            if(Key!=-1)
            {
                s[i]=s[x];
                s[i].r=s[x].r;
                s[x].r=Key;
                s[i].l=Key+1;
                printf("%d\n",Query(rt[s[i].r],1,n,s[i].lv,s[i].rv)-Query(rt[s[i].l-1],1,n,s[i].lv,s[i].rv));
            }
            else
            {
                s[i]=s[x];
                s[x].l=-1;
                printf("%d\n",Query(rt[s[i].r],1,n,s[i].lv,s[i].rv)-Query(rt[s[i].l-1],1,n,s[i].lv,s[i].rv));
            }
            
        }
        else
        {
            if(s[x].l==-1)
            {
                s[i].l=-1;
                printf("0\n");
            }
            else
            {
                if(s[x].lv<=y&&s[x].rv>y)
                {
                    s[i]=s[x];
                    s[i].lv=y+1;
                    s[i].rv=s[x].rv;
                    s[x].rv=y;
                    printf("%d\n",Query(rt[s[i].r],1,n,s[i].lv,s[i].rv)-Query(rt[s[i].l-1],1,n,s[i].lv,s[i].rv));
                }
                else if(y>=s[x].rv)
                {
                    s[i].l=-1;
                    printf("0\n");
                }
                else
                {
                    s[i]=s[x];
                    s[x].l=-1;
                    printf("%d\n",Query(rt[s[i].r],1,n,s[i].lv,s[i].rv)-Query(rt[s[i].l-1],1,n,s[i].lv,s[i].rv));
                }
            }
        }
    }
}

ABC245H

好题

首先考虑\(M\)为质数的情况,抛开\(k=0\),显然\(a_i(i\in[1,n-1])\)确定了\(a_n\)也即唯一确定

如果\(M=p^k\),\(k=r\times p^d\)考虑先分配\(d\)\(p\)\(n\)个数中,方案为\(\binom{n-d+1}{d}\),然后再对其他数填上与\(p\)互质的数共\((M-\frac{M}{p})\)

不过如果考虑\(k=0\)的情况,我们考虑容斥,减去不和法的,也即枚举\(d\),和上面的式子差不多,不过最后一项不确定,我们要乘上\(r\)的个数即\(\phi(p^{k-d})\)

如果都不是,考虑拆成若干个\(p^k\)的乘积,答案即为答案乘起来

Show Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=998244353;//
int Pow(int a,int b,int p)
{
    a%=p;///
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {///
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int n,m,k;
int C(int n,int m)
{
    int res=1;
    for(int i=n-m+1;i<=n;i++)
    {
        res=((long long)res*i)%MOD;
    }
    int Mp=1;
    for(int i=1;i<=m;i++)///
    {
        Mp=((long long)Mp*i)%MOD;
    }
    Mp=inv(Mp,MOD);
    return ((long long)res*Mp)%MOD;
}
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%lld %lld %lld",&k,&n,&m);
    int Res=1;
    for(int i=2;i<=m/i;i++)
    {
        if(m%i==0)
        {
            int q=0;
            int Mul=1;
            while(m%i==0)
            {
                m/=i;
                q++;
                Mul*=i;
            }
            if(n%Mul)
            {
                int d=0;
                while(n%i==0)
                {
                    d++;
                    n/=i;
                }
                int res=C(d+k-1,d);
                res=((long long)res*Pow(Mul-(Mul/i),k-1,MOD))%MOD;
                Res=((long long)Res*res)%MOD;
            }
            else
            {   
                int res=Pow(Mul,k,MOD);
                int Mf=Mul;
                for(int d=0;d<q;d++)
                {
                    int rv=C(d+k-1,d);
                    rv=((long long)rv*Pow(Mul-(Mul/i),k-1,MOD))%MOD;
                    rv=((long long)rv*((Mf-Mf/i)%MOD))%MOD;
                    res=((long long)res-rv+MOD)%MOD;
                    Mf/=i;
                }
                Res=((long long)Res*res)%MOD;
            }   
        }
    }
    if(m>1)
    {
        int i=m;
        int q=0;
        int Mul=1;
        while(m%i==0)
        {
            m/=i;
            q++;
            Mul*=i;
        }
        if(n%Mul)
        {
            int d=0;
            while(n%i==0)
            {
                d++;
                n/=i;
            }
            int res=C(d+k-1,d);
            res=((long long)res*Pow(Mul-(Mul/i),k-1,MOD))%MOD;
            Res=((long long)Res*res)%MOD;
        }
        else
        {   
            int res=Pow(Mul,k,MOD);
            int Mf=Mul;
            for(int d=0;d<q;d++)
            {
                int rv=C(d+k-1,d);
                rv=((long long)rv*Pow(Mul-(Mul/i),k-1,MOD))%MOD;
                rv=((long long)rv*((Mf-Mf/i)%MOD))%MOD;
                res=((long long)res-rv+MOD)%MOD;
                Mf/=i;
            }
            Res=((long long)Res*res)%MOD;
        }   
    }
    printf("%d\n",Res);
}

ABC282G

经典\(trick\)??

这种比大小可以记录前\(i\)维最后一位的排名

转移前缀和优化一下

Show Code
#include<bits/stdc++.h>
#define y1 djnb
#define y2 wpyy
#define x1 jjet
#define x2 ygokg
using namespace std;
const int MAXN=105;
int n,K,MOD;
int dp[2][MAXN][MAXN][MAXN];
int sum00[2][MAXN][MAXN][MAXN];
int Query(int i,int p,int x1,int x2,int y1,int y2)
{
    return ((((long long)sum00[i][x2][y2][p]-sum00[i][x2][y1-1][p]+MOD)%MOD-sum00[i][x1-1][y2][p]+MOD)%MOD+sum00[i][x1-1][y1-1][p])%MOD;
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d %d",&n,&K,&MOD);
    dp[1][1][1][0]=1;
    for(int p=0;p<=n;p++)
    {
        for(int j=0;j<=n;j++)
        {
            for(int k=0;k<=n;k++)
            {
                sum00[1][j][k][p]=dp[1][j][k][p];
            }
            
        }

        for(int j=0;j<=n;j++)
        {
            for(int k=1;k<=n;k++)
            {
                sum00[1][j][k][p]=((long long)sum00[1][j][k][p]+sum00[1][j][k-1][p])%MOD;
            }
        }
        for(int k=0;k<=n;k++)
        {
            for(int j=1;j<=n;j++)
            {
                sum00[1][j][k][p]=((long long)sum00[1][j][k][p]+sum00[1][j-1][k][p])%MOD;
            }
        }
    }
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            for(int k=1;k<=i;k++)
            {
                for(int p=0;p<=i;p++)
                {
                    dp[i&1][j][k][p]=((long long)Query((i&1)^1,p,1,j-1,k,n)+Query((i&1)^1,p,j,n,1,k-1))%MOD;
                    if(p)
                    {
                        dp[i&1][j][k][p]=((long long)dp[i&1][j][k][p]+Query((i&1)^1,p-1,1,j-1,1,k-1))%MOD;
                        dp[i&1][j][k][p]=((long long)dp[i&1][j][k][p]+Query((i&1)^1,p-1,j,n,k,n))%MOD;
                    }
                }
            }
        }
        for(int p=0;p<=n;p++)
        {
            for(int j=0;j<=n;j++)
            {
                for(int k=0;k<=n;k++)
                {
                    sum00[i&1][j][k][p]=dp[i&1][j][k][p];
                }
                
            }

            for(int j=0;j<=n;j++)
            {
                for(int k=1;k<=n;k++)
                {
                    sum00[i&1][j][k][p]=((long long)sum00[i&1][j][k][p]+sum00[i&1][j][k-1][p])%MOD;
                }
            }
            for(int k=0;k<=n;k++)
            {
                for(int j=1;j<=n;j++)
                {
                    sum00[i&1][j][k][p]=((long long)sum00[i&1][j][k][p]+sum00[i&1][j-1][k][p])%MOD;
                }
            }

        }
    }

    int Res=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            Res=((long long)Res+dp[n&1][i][j][K])%MOD;
        }
    }
    printf("%d\n",Res);
}

ABC275Ex

不难看出笛卡尔树

不难直接列出一个暴力\(dp\),\(dp_{u,x}=\min dp_{v,t}+tB_u-xB_u,t\ge \max A_u,x\)

发现\((t)B_u\)是个一次函数,我们大胆猜测这是个凸函数

直接用左偏树维护二阶导即可,你只需实现前缀删\(<A_u\)及斜率\(<0\)

这个删\(A_u\)不好搞,把它也插进去即可

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int n;
int A[MAXN];
int B[MAXN];

int ls[MAXN];
int rs[MAXN];
int st[MAXN];
int head;
struct Heap_node{
    int valx,lc,rc;
    int valk;
    int dist;
}Tree[MAXN*4];
int cnt_node;
int New(int x,int k)
{
    ++cnt_node;
    Tree[cnt_node].dist=Tree[cnt_node].rc=Tree[cnt_node].lc=0;
    Tree[cnt_node].valx=x;
    Tree[cnt_node].valk=k;
    return cnt_node;
}
int Merge(int x,int y)
{
    if((!x)||(!y))
    {
        return x+y;
    }
    if(Tree[x].valx>Tree[y].valx)
    {
        swap(x,y);
    }
    Tree[x].rc=Merge(Tree[x].rc,y);
    if(Tree[Tree[x].lc].dist<Tree[Tree[x].rc].dist)
    {
        swap(Tree[x].lc,Tree[x].rc);
    }
    Tree[x].dist=Tree[Tree[x].rc].dist+1;
    return x;
}
int Pop(int x)
{
    return Merge(Tree[x].lc,Tree[x].rc);
}
int rt[MAXN];
void Print(int x)
{
    vector<pair<int,int> >Used;
    while(rt[x])
    {
        pair<int,int> Use=make_pair(Tree[rt[x]].valx,Tree[rt[x]].valk);
        rt[x]=Pop(rt[x]);
        Used.push_back(Use);
        printf("%d %d\n",Use.first,Use.second);
    }

    for(int i=0;i<Used.size();i++)
    {
        rt[x]=Merge(rt[x],New(Used[i].first,Used[i].second));
    }

}

void dfs(int x)
{  
    if(ls[x])
    {
        dfs(ls[x]);
    }
    if(rs[x])
    {
        dfs(rs[x]);
    }
    if((!ls[x])&&(!rs[x]))
    {
        rt[x]=Merge(New(0,-B[x]),New(A[x],B[x]));
        return;
    }
    rt[x]=Merge(rt[ls[x]],rt[rs[x]]);

    rt[x]=Merge(rt[x],New(0,B[x]));
    rt[x]=Merge(rt[x],New(A[x],0));
    int lh=0;
    while(rt[x]&&(lh+Tree[rt[x]].valk<0||(Tree[rt[x]].valx<A[x])))
    {
        lh+=Tree[rt[x]].valk;
        rt[x]=Pop(rt[x]);
    }
    rt[x]=Merge(New(Tree[rt[x]].valx,lh),rt[x]);
    rt[x]=Merge(rt[x],New(0,-B[x]));
}
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&A[i]);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&B[i]);
    }
    
    for(int i=1;i<=n;i++)
    {
        while(head&&B[st[head]]<B[i])
        {
            head--;
        }
        if(!head)
        {
            ls[i]=st[head+1];
        }
        else
        {
            ls[i]=rs[st[head]];
            rs[st[head]]=i;
        }
        st[++head]=i;
    }
    dfs(st[1]);
    long long Res=0;
    int lk=Tree[rt[st[1]]].valk,lx=Tree[rt[st[1]]].valx;
    rt[st[1]]=Pop(rt[st[1]]);
    while(rt[st[1]])
    {
        int nk=Tree[rt[st[1]]].valk;
        int nx=Tree[rt[st[1]]].valx;
        Res+=((-(long long)lk)*(nx-lx));
       // printf("%d %d %d??\n",lx,nx,lk);
        lx=nx;
        lk+=nk;
        
        rt[st[1]]=Pop(rt[st[1]]);
    }
    printf("%lld\n",Res);
}

ABC276Ex

先把\(0\)去掉,实际上\(1,2\)之间就是个高斯消元

\(0\)的话我们就把\(1,2\)不涉及得矩形全填\(0\)即可

Show Code
#include<bits/stdc++.h>
#define x1 djnb
#define y1 djnbnnb
#define x2 djdjnb
#define y2 DJDJNBNBNB
using namespace std;
const int MAXN=2005;
struct Query{
    int x1,y1,x2,y2,val;
}query[MAXN];
int n,q;
map<pair<int,int>,int>Vis;
int id=0;
int Used=0;
struct Martix{
    bitset<MAXN*4>v[MAXN];
    void guess()
    {
        for(int r=1,c=1;r<=Used&&c<=id;r++,c++)
        {
            int Main=0;
            for(int i=r;i<=Used;i++)
            {
                if(v[i][c])
                {
                    Main=i;
                    break;
                }
            }
            if(!Main)
            {
                r--;
                continue;
            }
            swap(v[r],v[Main]);
            for(int i=1;i<=Used;i++)
            {
                if(i==r)
                {
                    continue;
                }
                if(v[i][c])
                {
                    v[i]^=v[r];
                }
            }
        }
    }
}A;
pair<int,int>V[MAXN*MAXN];
int Sv[MAXN][MAXN];
int cf[MAXN][MAXN];
int a[MAXN][MAXN];
int Cz[MAXN][MAXN];
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&q);
    
    for(int i=1;i<=q;i++)
    {
        scanf("%d %d %d %d %d",&query[i].x1,&query[i].x2,&query[i].y1,&query[i].y2,&query[i].val);
        if(query[i].val)
        {
            ++Used;
            cf[query[i].x1][query[i].y1]++;
            cf[query[i].x1][query[i].y2+1]--;
            cf[query[i].x2+1][query[i].y1]--;
            cf[query[i].x2+1][query[i].y2+1]++;
            if(!Vis[make_pair(query[i].x2,query[i].y2)])
            {
                Vis[make_pair(query[i].x2,query[i].y2)]=++id;
                V[id]=make_pair(query[i].x2,query[i].y2);
            }
            A.v[Used].set(Vis[make_pair(query[i].x2,query[i].y2)]);

            if(query[i].x1-1>=1)
            {
                if(!Vis[make_pair(query[i].x1-1,query[i].y2)])
                {
                    Vis[make_pair(query[i].x1-1,query[i].y2)]=++id;
                    V[id]=make_pair(query[i].x1-1,query[i].y2);
                }
                A.v[Used].set(Vis[make_pair(query[i].x1-1,query[i].y2)]);
            }

            if(query[i].y1-1>=1)
            {
                if(!Vis[make_pair(query[i].x2,query[i].y1-1)])
                {
                    Vis[make_pair(query[i].x2,query[i].y1-1)]=++id;
                    V[id]=make_pair(query[i].x2,query[i].y1-1);
                }
                A.v[Used].set(Vis[make_pair(query[i].x2,query[i].y1-1)]);
            }

            if(query[i].x1-1>=1&&query[i].y1-1>=1)
            {
                if(!Vis[make_pair(query[i].x1-1,query[i].y1-1)])
                {
                    Vis[make_pair(query[i].x1-1,query[i].y1-1)]=++id;
                    V[id]=make_pair(query[i].x1-1,query[i].y1-1);
                }
                A.v[Used].set(Vis[make_pair(query[i].x1-1,query[i].y1-1)]);
            }
        }
    }
    int hk=0;
    ++id;
    for(int i=1;i<=q;i++)
    {
        if(query[i].val)
        {
            ++hk;
            if(query[i].val==2)
            {
                A.v[hk].set(id);
            }
        }
    }
    // for(int i=1;i<=Used;i++)
    // {
    //     for(int j=1;j<=id;j++)
    //     {
    //         printf("%d",(int)A.v[i][j]);
    //     }
    //     printf("\n");
    // }
    A.guess();
    // printf("\n");
    // for(int i=1;i<=Used;i++)
    // {
    //     for(int j=1;j<=id;j++)
    //     {
    //         printf("%d",(int)A.v[i][j]);
    //     }
    //     printf("\n");
    // }
    for(int i=1;i<=Used;i++)
    {
        vector<int>Vrp;
        for(int j=1;j<id;j++)
        {
            if(A.v[i][j])
            {
                Vrp.push_back(j);
            }
        }
        if(A.v[i][id]&&(!Vrp.size()))
        {
            printf("No");
            return 0;
        }
        else
        {
            if(Vrp.size())
            {
                Sv[V[Vrp[0]].first][V[Vrp[0]].second]=A.v[i][id];
                for(int j=1;j<Vrp.size();j++)
                {
                    Sv[V[Vrp[j]].first][V[Vrp[j]].second]=0;    
                }
            }
            
        }
    }

    // for(int i=1;i<=n;i++)
    // {
    //     for(int j=1;j<=n;j++)
    //     {
    //         printf("%d ",Sv[i][j]);
    //     }
    //     printf("\n");
    // }
    for(int i=n;i>=1;i--)
    {
        for(int j=n;j>=1;j--)
        {
            Sv[i][j]=Sv[i][j]^Sv[i-1][j]^Sv[i-1][j-1]^Sv[i][j-1];
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cf[i][j]=cf[i][j]+cf[i-1][j]+cf[i][j-1]-cf[i-1][j-1];
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(cf[i][j])
            {
                if(Sv[i][j])
                {
                    a[i][j]=2;
                }
                else
                {
                    a[i][j]=1;
                }
            }
            else
            {
                a[i][j]=0;
            }
            Cz[i][j]=Cz[i-1][j]+Cz[i][j-1]-Cz[i-1][j-1]+(a[i][j]==0);
        }
    }

    for(int i=1;i<=q;i++)
    {
        if(query[i].val==0)
        {
            if(Cz[query[i].x2][query[i].y2]-Cz[query[i].x2][query[i].y1-1]-Cz[query[i].x1-1][query[i].y2]+Cz[query[i].x1-1][query[i].y1-1])
            {

            }
            else
            {
                printf("No");
                return 0;
            }
        }
    }

    printf("Yes\n");
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
}

ABC277Ex

一眼\(2-SAT\)

如果\((i,j)\)表示\(=j\)是否可行似乎不好弄

直接让\((i,j)\)表示\(\ge j\)是否可行即可

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e6+5;
int n,m;
int q;
int a,b,l,r;
int Hash(int x,int y)
{
    return (x-1)*(m+1)+(y+1);    
}
int Hashr(int x,int y)
{
    return (x-1)*(m+1)+(y+1)+(n*(m+1));
}
vector<int>g[MAXN];
int cnt_dfn;
int cnt_scc;
int dfn[MAXN];
int low[MAXN];
stack<int>st;
int scc[MAXN];
void dfs(int x)
{
    dfn[x]=++cnt_dfn;
    low[x]=dfn[x];
    st.push(x);
    for(int i=0;i<g[x].size();i++)
    {
        int v=g[x][i];
        if(dfn[v])
        {
            if(!scc[v])
            {
                low[x]=min(low[x],dfn[v]);
            }
        }
        else
        {
            dfs(v);
            low[x]=min(low[x],low[v]);
        }
    }
    if(low[x]==dfn[x])
    {
        ++cnt_scc;
        while(st.size())
        {
            scc[st.top()]=cnt_scc;
            if(st.top()==x)
            {
                st.pop();
                break;
            }
            st.pop();
        }
    }
}
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d %d",&n,&m,&q);
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {   
            if(j)
            {
                g[Hash(i,j)].push_back(Hash(i,j-1));  
            }
            if(j!=m)
            {
                g[Hashr(i,j)].push_back(Hashr(i,j+1));
            }
        }
        g[Hashr(i,0)].push_back(Hash(i,0));
        
    }

    for(int i=1;i<=q;i++)
    {
        scanf("%d %d %d %d",&a,&b,&l,&r);
        for(int j=0;j<=m;j++)
        {
            int Nl=l-j;
            int Nr=r-j;
            if(Nr+1<=m&&Nr+1>=0)
            {
                g[Hash(a,j)].push_back(Hashr(b,Nr+1));
                g[Hash(b,j)].push_back(Hashr(a,Nr+1));
            }
            else if(Nr+1<0)
            {
                g[Hash(a,j)].push_back(Hashr(a,j));
                g[Hash(b,j)].push_back(Hashr(b,j));
            }

            if(Nl+1<=m&&Nl+1>=0)
            {
                g[Hashr(a,j)].push_back(Hash(b,Nl+1));
                g[Hashr(b,j)].push_back(Hash(a,Nl+1));
            }
            else if(Nl+1>m)
            {
                g[Hashr(a,j)].push_back(Hash(a,j));
                g[Hashr(b,j)].push_back(Hash(b,j));
            }
            
        }
    }  
    for(int i=1;i<=2*n*(m+1);i++)
    {
        if(!dfn[i])
        {
            dfs(i);
        }
    }
    // for(int i=1;i<=2*n*(m+1);i++)
    // {
    //     for(int j=0;j<g[i].size();j++)
    //     {
    //         printf("%d %d\n",i,g[i][j]);
    //     }
    // }
    // printf("%d???\n",cnt_scc);
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {
            if(scc[Hash(i,j)]==scc[Hashr(i,j)])
            {
                printf("-1");
                return 0;
            }
        }
    }


    for(int i=1;i<=n;i++)
    {
        int NYH=0;
        for(int j=0;j<=m;j++)
        {
            if(scc[Hash(i,j)]<scc[Hashr(i,j)])
            {
                NYH=j;
            }
            else
            {
                break;
            }
        }
        printf("%d ",NYH);
    }
}

ABC281G

一眼分层然后\(dp\)

Show Code
#include<bits/stdc++.h>
using namespace std;
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
const int MAXN=505;
int n,MOD;
int Pw[MAXN*MAXN];
int C[MAXN][MAXN];
int dp[MAXN][MAXN];
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&MOD);
    C[0][0]=1;
    Pw[0]=1;
    for(int i=0;i<=n;i++)
    {
        C[i][0]=1;
        for(int j=1;j<=i;j++)
        {
            C[i][j]=((long long)C[i-1][j]+C[i-1][j-1])%MOD;
        }
    }

    for(int i=1;i<=n*n;i++)
    {
        Pw[i]=((long long)Pw[i-1]*2)%MOD;
    }
    dp[1][1]=1;
        for(int j=2;j<=n;j++)
        {
            for(int k=1;k<=j;k++)
            {
                for(int l=1;l<=n;l++)
                {
                    int Rj=dp[j-k][l];
                    Rj=((long long)Rj*Pow(((long long)Pw[l]-1+MOD)%MOD,k,MOD))%MOD;
                    dp[j][k]=((long long)dp[j][k]+Rj)%MOD;
                }
                dp[j][k]=((long long)dp[j][k]*C[n-1-(j-k)][k])%MOD;
                dp[j][k]=((long long)dp[j][k]*Pw[(k*(k-1))/2])%MOD;
            }
        }
    int Res=0;
        for(int k=1;k<=n;k++)
        {
            int tk=dp[n-1][k];
            tk=((long long)tk*(Pw[k]-1)%MOD);
            Res=((long long)Res+tk)%MOD;
        }
    printf("%d\n",Res);
}

ABC279G

男泵

\(dp_{i,0/1}\)表示前\(k-1\)得状态就行了

阿哲,最开始想得前\(k\),后面被带偏了/kk

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=1e6+5;
int n,k,c;
int dp[MAXN][2];
int sum[MAXN][2];
int Get(int x,int op)
{
    if(x<0)
    {
        return 0;
    }
    return sum[x][op];
}
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d %d",&n,&k,&c);
    for(int i=1;i<=n;i++)
    {
        // for(int j=1;j<=(i-k)+1;j++)
        // {
        //     dp[i][0]=((long long)dp[i][0]+(((long long)c-1)*dp[j][0]+dp[j][1])%MOD)%MOD;
        // }
        dp[i][0]=((long long)dp[i][0]+((long long)c-1)*(Get(i-k+1,0))%MOD)%MOD;
        dp[i][0]=((long long)dp[i][0]+(Get(i-k+1,1)))%MOD;
        dp[i][0]=((long long)dp[i][0]+c)%MOD;

        // for(int j=i-k+2;j<=i-1;j++)
        // {
        //     dp[i][1]=((long long)dp[i][1]+(((long long)c-1)*dp[j][0]+dp[j][1])%MOD)%MOD;
        // }
        dp[i][1]=((long long)dp[i][1]+((long long)c-1)*((Get(i-1,0)-Get(i-k+1,0)+MOD)%MOD)%MOD)%MOD;
        dp[i][1]=((long long)dp[i][1]+((Get(i-1,1)-Get(i-k+1,1)+MOD)%MOD))%MOD;

        sum[i][0]=((long long)sum[i-1][0]+dp[i][0])%MOD;
        sum[i][1]=((long long)sum[i-1][1]+dp[i][1])%MOD;
    }
    printf("%d\n",((long long)dp[n][0]+dp[n][1])%MOD);
}

ABC278G

自闭了

\(l\not = r\)明显先手必胜

否则\(l=r\)直接\(sg\),输出方案得话就看\(sg=0\)得局面

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2005;
int n,l,r;
int a,b;
int dp[MAXN];
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    cin>>n>>l>>r;
    if(l==r)
    {
        for(int i=0;i<l;i++)
        {
            dp[i]=0;
        }
        for(int i=l;i<=n;i++)
        {
            vector<int>V;
            for(int j=0;j<=i-l;j++)
            {
                V.push_back(dp[j]^dp[i-l-j]);       
            }
            sort(V.begin(),V.end());
            V.erase(unique(V.begin(),V.end()),V.end());
            dp[i]=V.size();
            for(int j=0;j<V.size();j++)
            {
                if(V[j]!=j)
                {
                    dp[i]=j;
                    break;
                }
            }
        }
        if(dp[n])
        {
            cout<<"First"<<endl;
            set<pair<int,int> >V;
            V.insert(make_pair(1,n));
            int Sum=dp[n];
            pair<int,int>MRk;
            for(auto it=V.begin();it!=V.end();it++)
            {
                pair<int,int>tmp=(*it);
                int L=tmp.first;
                int R=tmp.second;
                int Ns=Sum^(dp[tmp.second-tmp.first+1]);
                int Ki=-1;
                for(int i=0;i<=(R-L+1)-l;i++)
                {
                    if((Ns^dp[i]^dp[(R-L+1)-l-i])==0)
                    {
                        Ki=i;
                        break;
                    }
                }
                if(Ki!=-1)
                {
                    cout<<Ki+L<<" "<<l<<endl;
                    MRk=(*it);
                    Sum=Ns;
                    if(L<=L+Ki-1)
                    {
                        V.insert(make_pair(L,L+Ki-1));
                        Sum^=dp[Ki];
                    }                
                    if(Ki+L+l<=R)
                    {
                        V.insert(make_pair(Ki+L+l,R));
                        Sum^=dp[R-(Ki+L+l)+1];
                    }
                    break;
                }
            }
            V.erase(MRk);
            cin>>a>>b;
            while((a)&&(a!=-1))
            {
                b=a+b-1;
                auto it=V.upper_bound(make_pair(a,n+1));
                --it;   
                Sum^=dp[(*it).second-(*it).first+1];
                auto Tmp=(*it);
                V.erase(it);
                if(Tmp.first<a)
                {
                    V.insert(make_pair(Tmp.first,a-1));
                    Sum^=dp[a-Tmp.first];
                }
                if(b+1<=Tmp.second)
                {
                    V.insert(make_pair(b+1,Tmp.second));
                    Sum^=dp[Tmp.second-b];
                }
                pair<int,int>Mrk;
                for(it=V.begin();it!=V.end();it++)
                {
                    pair<int,int>tmp=(*it);
                    int L=tmp.first;
                    int R=tmp.second;
                    int Ns=Sum^(dp[tmp.second-tmp.first+1]);
                    int Ki=-1;
                    for(int i=0;i<=(R-L+1)-l;i++)
                    {
                        if((Ns^dp[i]^dp[(R-L+1)-l-i])==0)
                        {
                            Ki=i;
                            break;
                        }
                    }
                    if(Ki!=-1)
                    {
                        cout<<Ki+L<<" "<<l<<endl;
                        // cout<<a<<" "<<b<<endl;
                        Mrk=(*it);
                        Sum=Ns;
                        if(L<=L+Ki-1)
                        {
                            V.insert(make_pair(L,L+Ki-1));
                            Sum^=dp[Ki];
                        }                
                        if(Ki+L+l<=R)
                        {
                            V.insert(make_pair(Ki+L+l,R));
                            Sum^=dp[R-(Ki+L+l)+1];
                        }
                        break;
                    }
                }
                V.erase(Mrk);
                cin>>a>>b;
            }

        }
        else
        {
            cout<<"Second"<<endl;

            set<pair<int,int> >V;
            V.insert(make_pair(1,n));
            int Sum=dp[n];
            cin>>a>>b;
            while((a)&&(a!=-1))
            {
                b=a+b-1;
                auto it=V.upper_bound(make_pair(a,n+1));
                --it;   
                Sum^=dp[(*it).second-(*it).first+1];
                auto Tmp=(*it);
                V.erase(it);
                if(Tmp.first<a)
                {
                    V.insert(make_pair(Tmp.first,a-1));
                    Sum^=dp[a-Tmp.first];
                }
                if(b+1<=Tmp.second)
                {
                    V.insert(make_pair(b+1,Tmp.second));
                    Sum^=dp[Tmp.second-b];
                }
                pair<int,int>Mrk;
                for(it=V.begin();it!=V.end();it++)
                {
                    pair<int,int>tmp=(*it);
                    int L=tmp.first;
                    int R=tmp.second;
                    int Ns=Sum^(dp[tmp.second-tmp.first+1]);
                    int Ki=-1;
                    for(int i=0;i<=(R-L+1)-l;i++)
                    {
                        if((Ns^dp[i]^dp[(R-L+1)-l-i])==0)
                        {
                            Ki=i;
                            break;
                        }
                    }
                    if(Ki!=-1)
                    {
                        cout<<Ki+L<<" "<<l<<endl;
                        // cout<<a<<" "<<b<<endl;
                        Mrk=(*it);
                        Sum=Ns;
                        if(L<=L+Ki-1)
                        {
                            V.insert(make_pair(L,L+Ki-1));
                            Sum^=dp[Ki];
                        }                
                        if(Ki+L+l<=R)
                        {
                            V.insert(make_pair(Ki+L+l,R));
                            Sum^=dp[R-(Ki+L+l)+1];
                        }
                        break;
                    }
                }
                V.erase(Mrk);
                cin>>a>>b;
            }
        }
    }
    else
    {
        cout<<"First"<<endl;
        int Now=l;
        if((n&1)!=(Now&1))
        {
            Now++;
        }
        int x=(n-Now)/2;
        cout<<x+1<<" "<<Now<<endl;
        cin>>a>>b;
        while(a&&(a!=-1))
        {
            int L=a;
            int R=a+b-1;
            swap(L,R);
            L=n-L+1;
            R=n-R+1;
            cout<<L<<" "<<R-L+1<<endl;
            cin>>a>>b;
        }
        
    }
}

ABC277G

没看出来套路自闭了

考虑维护\(dp_{i,j,1/2}\)表示走到\(i\)用了\(j\)时当前\(x/x^2\)的期望

答案就是这些加起来

注意常数项也要算进去

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=3005;
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int Inv[MAXN];
int n,m,k;
int x,y;
int c[MAXN];
vector<int>g[MAXN];
int dp[MAXN][MAXN][3];
int f[MAXN][MAXN];
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&c[i]);
        Inv[i]=inv(i,MOD);
    }
    f[1][0]=1;
    dp[1][0][0]=0;
    dp[1][0][1]=0;
    for(int i=1;i<=k;i++)
    {
        for(int j=1;j<=n;j++)
        {
            for(int p=0;p<(g[j].size());p++)
            {
                int v=g[j][p];
                f[j][i]=((long long)f[j][i]+((long long)f[v][i-1]*Inv[g[v].size()])%MOD)%MOD;
                if(!c[j])
                {
                    dp[j][i][0]=((long long)dp[j][i][0]+((((long long)dp[v][i-1][0]+f[v][i-1])%MOD)*Inv[g[v].size()])%MOD)%MOD;
                    dp[j][i][1]=((long long)dp[j][i][1]+((((long long)dp[v][i-1][1]+2ll*dp[v][i-1][0]+f[v][i-1])%MOD)*Inv[g[v].size()])%MOD)%MOD;
                }
                else
                {
                    dp[j][i][0]=((long long)dp[j][i][0]+(((long long)dp[v][i-1][0])*Inv[g[v].size()])%MOD)%MOD;
                    dp[j][i][1]=((long long)dp[j][i][1]+(((long long)dp[v][i-1][1])*Inv[g[v].size()])%MOD)%MOD;
                }

            }
        }
    }

    int Res=0;
    for(int i=1;i<=k;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(c[j])
            {
                int tot=dp[j][i][1];
                Res=((long long)Res+tot)%MOD;
            }
        }
    }
    printf("%d\n",Res);
}

ABC276G

\(\sum\limits_{i=0}^{n-1}(-1)^i\binom{n-1}{i}\sum\limits_{j=i}^m\binom{m-2j+n}{n-1}\binom{j-1}{i-1}\)

算了,换个思路

差分一下,得到\(b\)

要求即使\(b_i\not \equiv0 \bmod 3\)\(\sum b_i\le M\)

不考虑\(b_i\not \equiv 0 \bmod 3\),方案数为\(\binom{n+M-1}{M}\)

先全部\(\bmod 3\),那就只能填\(1,2\)

枚举和为\(m\)

则方案数为\(\sum\limits_{m=n-1}\binom{n-1}{m-(n-1)} \sum\limits_{l=0,m+3l\le M}\binom{l+n-2}{l}\)

第一个好像要枚举\(\bmod 3\)是多少吧

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=2e7+5;
int n,m;
int fac[MAXN];
int inv_fac[MAXN];
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int C(int n,int m)
{
    if(n<m||m<0)
    {
        return 0;
    }
    if(n==m||m==0)
    {
        return 1;
    }
    return ((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD;
}
int f[MAXN];
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    fac[0]=1;
    for(int i=1;i<=MAXN-5;i++)
    {
        fac[i]=((long long)fac[i-1]*i)%MOD;
    }
    inv_fac[MAXN-5]=inv(fac[MAXN-5],MOD);
    for(int i=MAXN-5-1;i>=1;i--)
    {
        inv_fac[i]=((long long)inv_fac[i+1]*(i+1))%MOD;
    }
    scanf("%d %d",&n,&m);
    f[0]=1;
    for(int i=1;i<=m;i++)
    {
        f[i]=((long long)f[i-1]+C(i+n-1,i))%MOD;
    }   
    int Res=0;
    for(int k=0;k<=2;k++)
    {
        for(int i=n-1;i<=2*(n-1);i++)
        {
            int vl=C(n-1,(i-(n-1)));
            int Ct=(m-i-k)/3;
            if(m-i-k>=0)
            {
                vl=((long long)vl*f[Ct])%MOD;
                Res=((long long)Res+vl)%MOD;
                //printf("%d %d %d::\n",k,i,vl);
            }
            
        }
    }
    
    printf("%d\n",Res);
}

ABC275G

首先转化一下无限那个条件

这个就相当于我们的物品可以取实数个

这样我们可以把所有物品的价值先定为\(1\),代价为\(\dfrac{a_i}{c_i}\)\(\dfrac{b_i}{c_i}\)

答案即为\(\dfrac{\sum x_i}{\max(\sum a_ix_i,\sum b_ix_i)}\)

不妨取\(\sum x_i=1\),我们即要\(max(\sum a_ix_i,\sum b_ix_i)\)最小

二分这玩意为\(mid\),则\(max(\sum a_ix_i,\sum b_ix_i)\le mid\)

我们再把代价改为\(a_i-mid\)

然后就是\(\sum a_ix_i\le 0\& \sum b_ix_i\le 0\)

\(a_i<0,b_i<0\)一定满足

否则我们可以只考虑\(a_i>0,b_i<0\)\(a_i<0,b_i>0\)

我们可以把它再变换个形式\((\dfrac{-a_i}{b_i},-1)\)\((-1,\dfrac{b_i}{-a_i})\),我们就要取最小的那个

\(A=\dfrac{-a_i}{b_i},B=\dfrac{b_i}{-a_i}\)

即是否存在\(xA+x-1\le 0\)\(-x+(1-x)B \le 0\)

\(x\le \dfrac{1}{A+1}\)\(\dfrac{B}{B+1}\le x\)

\(\dfrac{B}{B+1}\le \dfrac{1}{A+1}\)\(AB\le 1\)

Show Code
#include<bits/stdc++.h>
#define eps 1e-7
using namespace std;
const int MAXN=2e5+5;
int n;
int a[MAXN];
int b[MAXN];
int c[MAXN];
long double A[MAXN];
long double B[MAXN];
bool check(long double mid)
{
    long double Ap=0x3f3f3f3f,Bp=0x3f3f3f3f;
    for(int i=1;i<=n;i++)
    {
        A[i]=(a[i]*1.0/c[i])-mid;
        B[i]=(b[i]*1.0/c[i])-mid;
        if(A[i]>=0&&B[i]>=0)
        {
            continue;
        }
        if(A[i]<=0&&B[i]<=0)
        {
            return 1;
        }

        if(A[i]<0)
        {
            Bp=min(Bp,(-B[i]/A[i]));
        }
        else
        {
            Ap=min(Ap,(-A[i])/B[i]);
        }
    }

    return (Ap*Bp<=1);
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d %d",&a[i],&b[i],&c[i]);
    }
    long double l=0;
    long double r=1e18;
    while(r-l>eps)
    {
        long double mid=(l+r)*1.0/2;
        if(check(mid))
        {
            r=mid;
        }
        else
        {
            l=mid;
        }
    }
    l=(1.0/l);
    printf("%.9LF",l);
}

ABC274G

调了半天结果数组开小了

现在精神不大正常

最开始题看错了,看清楚后发现是覆盖一整行或列果断最小点覆盖

Show Code
#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
const int MAXN=405;
int n,m;
char s[MAXN][MAXN];
int Idr,Idc;
int c[MAXN][MAXN];
int r[MAXN][MAXN];
struct Edge{
    int nxt,to,val;
}edge[MAXN*MAXN*8];
int head[MAXN*MAXN];
int cnt_edge=1;
void Add(int u,int v,int val)
{
    ++cnt_edge;
    edge[cnt_edge].nxt=head[u];
    edge[cnt_edge].val=val;
    edge[cnt_edge].to=v;
    head[u]=cnt_edge;
    return;
}
void add(int u,int v,int val)
{
    Add(u,v,val);
    Add(v,u,0);
}
int S,T;
int dis[MAXN*MAXN];
int arc[MAXN*MAXN];
int bfs()
{
    memset(dis,-1,sizeof(dis));
    queue<int>q;
    q.push(S);
    dis[S]=0;
    while(q.size())
    {
        int u=q.front();
        q.pop();
        arc[u]=head[u];
        for(int i=head[u];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            int w=edge[i].val;
            if(!w)
            {
                continue;
            }
            if(dis[v]!=-1)
            {
                continue;
            }
            dis[v]=dis[u]+1;
            q.push(v);
        }
    }
    return dis[T]!=-1;
}
int dfs(int x,int Cap)
{   
    if(x==T)
    {
        return Cap;
    }
    int Used=0;
    for(int i=arc[x];i;i=edge[i].nxt)
    {
        arc[x]=i;
        int v=edge[i].to;
        int w=edge[i].val;
        if(dis[v]==dis[x]+1)
        {
            if(!w)
            {
                continue;
            }
            int Flow=dfs(v,min(Cap,w));
            edge[i].val-=Flow;
            edge[i^1].val+=Flow;
            Used+=Flow;
            Cap-=Flow;
            if(!Cap)
            {
                return Used;
            }
        }
    }
    return Used;
}
int dinic()
{
    int Maxflow=0;
    while(bfs())
    {
        int Flow;
        while((Flow=dfs(S,INF)))
        {
            Maxflow+=Flow;
        }
       // cerr<<Maxflow<<endl;
    }
    return Maxflow;
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s[i]+1);
    }
    for(int i=1;i<=n;i++)
    {
        int las=1;
        s[i][m+1]='#';
        for(int j=1;j<=m+1;j++)
        {
            if(s[i][j]=='#')
            {
                if(las<=j-1)
                {
                    ++Idr;
                    for(int k=las;k<=j-1;k++)
                    {
                        r[i][k]=Idr;
                    }
                }
                las=j+1;
            }   
        }
        
    }

    for(int i=1;i<=m;i++)
    {
        int las=1;
        s[n+1][i]='#';
        for(int j=1;j<=n+1;j++)
        {
            if(s[j][i]=='#')
            {
                if(las<=j-1)
                {
                    ++Idc;
                    for(int k=las;k<=j-1;k++)
                    {
                        c[k][i]=Idc;
                    }
                }
                las=j+1;
            }   
        }
    }
    S=0;
    T=Idc+Idr+1;
    for(int i=1;i<=Idr;i++)
    {
        add(S,i,1);
    }

    for(int i=1;i<=Idc;i++)
    {
        add(i+Idr,T,1);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(s[i][j]=='.')
            {
                add(r[i][j],c[i][j]+Idr,1);
            }
        }
    }
    printf("%d\n",dinic());
}

ABC220Ex

感觉很像\(2^{\frac{n}{2}}\),不过完全没思路

直接令\(S\)为前\(\dfrac{n}{2}\)个点组成点集

\(f_1(s)\)为选\(s\)的边的奇偶,\(s\sube S\),\(f_2(t)\)为选\(t\)且只有\(t\)的边

我们可以发现边就是由\(f_1(s)\oplus f_2(t)\)再算上分别连在\(S/s,t\)的边组成

对于分别连在\(s,t\)的边,我们考虑先处理出\(g(s)\)表示在\(T\)中与\(s\)有奇数条边相连的点集

那么答案即是\(\sum[f_1(s)\oplus f_2(s)\oplus(popcount(g(s)\&t) \& 1\ )=0]\)

枚举\(popcount(g(s)\&t)\),即\(\sum\limits_{p=0}\sum\limits_{popcount(g(s)\& t)=p}[f_1(s)\oplus f_2(t)\oplus(p\&1)=0]\)

考虑计算\(\sum\limits_{p=0}\sum\limits_{g(s)\& t=p}[f_1(s)\oplus f_2(t)=0/1]\),这看着很与卷积

枚举\(g(s)\)取值时\(f_1(s)=0/1\)的方案数即可

Show Code
#include<bits/stdc++.h>
using namespace std;
int N;
int m;
int x,y;
vector<int>g[45];
int f1[(1<<20)+5];
int f2[(1<<20)+5];
int f[(1<<20)+5];
long long c1[2][(1<<20)+5];
long long c2[2][(1<<20)+5];
long long h[2][(1<<20)+5];
int n1,n2;
void FWT(long long *a)
{
    for(int len=2;len<=(1<<n2);len<<=1)
    {
        for(int i=0;i<(1<<n2);i+=len)
        {
            for(int j=i;j<i+(len>>1);j++)
            {
                long long tmp1=a[j];
                long long tmp2=a[j+(len>>1)];
                a[j]=tmp1+tmp2;
                a[j+(len>>1)]=tmp2;
            }
        }
    }
}
void IFWT(long long *a)
{
    for(int len=2;len<=(1<<n2);len<<=1)
    {
        for(int i=0;i<(1<<n2);i+=len)
        {
            for(int j=i;j<i+(len>>1);j++)
            {
                long long tmp1=a[j];
                long long tmp2=a[j+(len>>1)];
                a[j]=tmp1-tmp2;
                a[j+(len>>1)]=tmp2;
            }
        }
    }
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&N,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&x,&y);
        x--;
        y--;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    n1=(N/2);
    n2=N-(N/2);
    for(int i=1;i<(1<<n1);i++)
    {
        int lob=__builtin_ctz(i);
        int ret=(i^(1<<lob));
        f1[i]=f1[ret];
        f[i]=f[ret];
        for(int j=0;j<g[lob].size();j++)
        {
            int v=g[lob][j];
            if(((!((ret>>(v))&1))&&(v<n1))||(v>=n1))
            {
                f1[i]^=1;
            }
            if(v>=n1)
            {
                f[i]^=(1<<(v-n1));
            }
        }
       // printf("%d %d %d---\n",i,f1[i],f[i]);
    }

    for(int i=1;i<(1<<n2);i++)
    {
        int lob=__builtin_ctz(i);
        int ret=(i^(1<<lob));
        f2[i]=f2[ret];
        
        for(int j=0;j<g[lob+n1].size();j++)
        {
            int v=g[lob+n1][j];
            if((v>=n1)&&(!((ret>>((v-n1)))&1)))
            {
                f2[i]^=1;
            }
        }
        // printf("%d %d\n",i,f2[i]);
    }
    int mx=(1<<n1)-1;
    for(int i=0;i<(1<<n1);i++)
    {
        c1[f1[i^mx]][f[i]]++;
    }   
    for(int i=0;i<(1<<n2);i++)
    {
        c2[f2[i]][i]++;
    }
    // for(int i=0;i<(1<<n2);i++)
    // {
    //     for(int op=0;op<=1;op++)
    //     {
    //         printf("%d %d %d\n",op,i,c1[op][i]);
    //     }
    // }
    // printf("-----\n");

    
    // for(int i=0;i<(1<<n2);i++)
    // {
    //     for(int op=0;op<=1;op++)
    //     {
    //         printf("%d %d %d\n",op,i,c2[op][i]);
    //     }
    // }
    // printf("-----\n");
    FWT(c1[0]);
    FWT(c2[0]);
    FWT(c1[1]);
    FWT(c2[1]);
    // for(int i=0;i<(1<<n2);i++)
    // {
    //     for(int op=0;op<=1;op++)
    //     {
    //         printf("%d %d %d\n",op,i,c1[op][i]);
    //     }
    // }
    // printf("-----\n");
    // for(int i=0;i<(1<<n2);i++)
    // {
    //     for(int op=0;op<=1;op++)
    //     {
    //         printf("%d %d %d\n",op,i,c2[op][i]);
    //     }
    // }
    // printf("-----\n");
    for(int i=0;i<(1<<n2);i++)
    {
        for(int op1=0;op1<=1;op1++)
        {
            for(int op2=0;op2<=1;op2++)
            {
                h[op1^op2][i]+=c1[op1][i]*c2[op2][i];
                //printf("%d %d %d %d??\n",op1,op2,i,c1[op1][i]*c2[op2][i]);
            }
        }
    }
    // for(int i=0;i<(1<<n2);i++)
    // {
    //     for(int op=0;op<=1;op++)
    //     {
    //         printf("%d %d %d\n",op,i,h[op][i]);
    //     }
    // }
    // printf("-----\n");
    IFWT(h[0]);
    IFWT(h[1]);

    long long Res=0;
    for(int i=0;i<(1<<n2);i++)
    {
        Res+=h[(__builtin_popcount(i))&1][i];
    }
    printf("%lld\n",Res);

}

ABC273G

简单\(dp\),考虑前\(i\)行剩了\(j\)\(1\)

转移有点多

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=5005;
int n;
int R[MAXN];
int C[MAXN];
int dp[MAXN][MAXN];
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    int Sum=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&R[i]);
        Sum+=R[i];
    }
    int Spt=0;
    int c1=0;
    int c2=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&C[i]);
        Spt+=C[i];
        if(C[i]==1)
        {
            c1++;
        }
        else
        {
            c2++;
        }
    }
    if(Sum!=Spt)
    {
        printf("0");
        return 0;
    }
  //  cerr<<"fc"<<endl;
    dp[0][c1]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            if((Sum-j)&1)
            {
                continue;
            }
            if(!dp[i-1][j])
            {
                continue;
            }
            int k=(Sum-j)/2;
         //   printf("%d %d %d %d:::\n",i-1,j,k,dp[i-1][j]);
            if(R[i]==0)
            {
                dp[i][j]=((long long)dp[i][j]+dp[i-1][j])%MOD;
            }
            else if(R[i]==1)
            {
                if(j)
                {
                    dp[i][j-1]=((long long)dp[i][j-1]+((long long)dp[i-1][j]*j)%MOD)%MOD;
                    
                }
                dp[i][j+1]=((long long)dp[i][j+1]+((long long)dp[i-1][j]*k)%MOD)%MOD;
            }
            else
            {
                dp[i][j]=((long long)dp[i][j]+((long long)dp[i-1][j]*k)%MOD)%MOD;
                dp[i][j]=((long long)dp[i][j]+(((long long)dp[i-1][j]*k*j)%MOD))%MOD;
                if(j>=2)
                {
                    dp[i][j-2]=((long long)dp[i][j-2]+(((long long)dp[i-1][j]*(j*(j-1)/2))%MOD))%MOD;
                }
                if(k>=2)
                {
                    dp[i][j+2]=((long long)dp[i][j+2]+((long long)dp[i-1][j]*(k*(k-1)/2))%MOD)%MOD;
                }
                
            }
        //    printf("%d---\n",dp[2][1]);
        }

        // for(int j=0;j<=n;j++)
        // {
        //     printf("%d %d %d\n",i,j,dp[i][j]);
        // }
        Sum-=R[i];
    }
    printf("%d\n",dp[n][0]);
    
}
// 10
// 10 75 38
// 6 30 99
// 10 17 51
// 1 76 53
// 6 89 48
// 8 14 84
// 1 14 31
// 10 33 33
// 2 85 38
// 10 72 29

ABC272G

随机化爬

Show Code
#include<bits/stdc++.h>
using namespace std;
int Abs(int x)
{
    return x>0?x:-x;
}
mt19937 Niuzi(998244353);
const int MAXN=5005;
int n;
int a[MAXN];
map<int,int>Vis;
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    int T=50;
    while(T--)
    {
        int x=Niuzi()%n+1;
        int t=50;
        while(t--)
        {
            int y=Niuzi()%n+1;
            if(x==y)
            {
                continue;
            }   
            int d=Abs(a[x]-a[y]);
            for(int z=2;z*z<=d;z++)
            {
                if((d%z==0))
                {
                    if(z>2)
                    {
                        while(d%z==0)
                        {
                            d/=z;
                        }
                        Vis.clear();
                        int maxi=0;
                        for(int i=1;i<=n;i++)
                        {   
                            Vis[(a[i])%z]++;
                            maxi=max(maxi,Vis[a[i]%z]);
                        }
                        if(maxi>(n/2))
                        {
                            printf("%d",z);
                            return 0;
                        }
                    }
                }
            }
            if(d>2)
            {
                int z=d;
                Vis.clear();
                int maxi=0;
                for(int i=1;i<=n;i++)
                {   
                    Vis[(a[i])%z]++;
                    maxi=max(maxi,Vis[a[i]%z]);
                }
                if(maxi>(n/2))
                {
                    printf("%d",z);
                    return 0;
                }
            }

        }
    }
    printf("-1\n");
}
// 10
// 10 75 38
// 6 30 99
// 10 17 51
// 1 76 53
// 6 89 48
// 8 14 84
// 1 14 31
// 10 33 33
// 2 85 38
// 10 72 29

ABC325G

可以去竞选弱智吧吧主了/kk

第一眼的思路竟是把所有可以删完的区间处理出来,然后选出最长的不交区间

结果实际上没必要这样处理,直接\(dp\)答案即可,直接找第一个\(o\)\(i\)处的\(f\)即可

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=305;
char s[MAXN];
int K;
int dp[MAXN][MAXN];
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%s",s+1);
    scanf("%d",&K);
    int n=strlen(s+1);
    memset(dp,0x3f,sizeof(dp));
    for(int i=1;i<=n;i++)
    {
        dp[i][i]=1;
        dp[i][i-1]=0;
        dp[i+1][i]=0;
    }
    for(int len=2;len<=n;len++)
    {
        for(int l=1;l+len-1<=n;l++)
        {
            int r=l+len-1;
            for(int k=l;k<r;k++)
            {
                dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
            }
            if(s[l]=='o')
            {
                for(int k=l;k<r;k++)
                {
                    if(dp[l+1][k]==0&&s[k+1]=='f')
                    {
           //             printf("%d %d %d???\n",l,r,k);
                        dp[l][r]=min(dp[l][r],max(dp[k+2][r]-K,0));
                    }
                }
            }
        }
    }
   // printf("%d\n",dp[2][5]);
    printf("%d\n",dp[1][n]);
}

ABC271G

一眼矩乘

初值付错了调了半天

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
long long n;
int x,y;
char s[31];
int cost[25][25];
struct Martix{
    int val[24][24];
    void clear()
    {
        memset(val,0,sizeof(val));
    }
    void init()
    {
        clear();
        for(int i=0;i<24;i++)
        {
            val[i][i]=1;
        }
    }
    Martix operator*(const Martix x)const{
        Martix Res;
        Res.clear();
        for(int k=0;k<24;k++)
        {
            for(int i=0;i<24;i++)
            {
                for(int j=0;j<24;j++)
                {
                    Res.val[i][j]=((long long)Res.val[i][j]+((long long)val[i][k]*x.val[k][j])%MOD)%MOD;
                }
            }
        }
        return Res;
    }
}A,B;
Martix Pw(Martix Base,long long b)
{
    Martix Res;
    Res.init();
    while(b)
    {
        if(b&1)
        {
            Res=Res*Base;
        }
        Base=Base*Base;
        b>>=1;
    }
    return Res;
}
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%lld %d %d",&n,&x,&y);
    x=((long long)x*inv(100,MOD))%MOD;
    y=((long long)y*inv(100,MOD))%MOD;
    scanf("%s",s);
    int p=1;
    for(int i=0;i<24;i++)
    {
        if(s[i]=='T')
        {
            p=((long long)p*(1ll-x+MOD)%MOD)%MOD;
        }
        else
        {
            p=((long long)p*(1ll-y+MOD)%MOD)%MOD;
        }
    }
    for(int i=0;i<24;i++)
    {
        for(int j=0;j<24;j++)
        {
            int Now=(i+1)%24;
            int P=1;
            while(Now!=j)
            {
                if(s[Now]=='T')
                {
                    P=((long long)P*(1ll-x+MOD)%MOD)%MOD;
                }
                else
                {
                    P=((long long)P*(1ll-y+MOD)%MOD)%MOD;
                }
                Now++;
                Now%=24;
            }
            int v;
            if(s[j]=='T')
            {
                v=x;
            }
            else
            {
                v=y;
            }
         //   printf("%d %d %d %d",i+1,j+1,P,v);
            P=((long long)P*v)%MOD;
            P=((long long)P*inv((1ll-p+MOD)%MOD,MOD))%MOD;
        //    printf(" %d\n",P);
            cost[i][j]=P;
       //     printf("%d\n",cost[2][1]);
        }
    }
    A.clear();
    for(int i=0;i<24;i++)
    {
        for(int j=0;j<24;j++)
        {
            A.val[i][j]=cost[i][j];
        //    printf("%d ",cost[i][j]);
        }
     //   printf("\n");
    }
    B.clear();
    B.val[0][23]=1;
    B=B*Pw(A,n);
    int Res=0;
    for(int i=0;i<24;i++)
    {
        if(s[i]=='A')
        {   
            Res=((long long)Res+B.val[0][i])%MOD;
        }
    }
    printf("%d\n",Res);
}

ABC326G

简单最小割

Show Code
#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
const int MAXN=200005;
struct Edge{
    int val,to,nxt;
}edge[MAXN];
int head[MAXN];
int cnt_edge=1;
void Add(int u,int v,int val)
{
    ++cnt_edge;
    edge[cnt_edge].nxt=head[u];
    edge[cnt_edge].val=val;
    edge[cnt_edge].to=v;
    head[u]=cnt_edge;
    return;
}
void add(int u,int v,int val)
{
    Add(u,v,val);
    Add(v,u,0);
}
int S,T;
int arc[MAXN];
int dis[MAXN];
int bfs()
{
    memset(dis,0x3f,sizeof(dis));
    queue<int>q;
    dis[S]=0;
    q.push(S);
    while(q.size())
    {
        int u=q.front();
        arc[u]=head[u];
        q.pop();
        for(int i=head[u];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            int w=edge[i].val;
            if(!w)
            {
                continue;
            }
            if(dis[v]!=0x3f3f3f3f)
            {
                continue;
            }
            dis[v]=dis[u]+1;
            q.push(v);
        }
    }
    return dis[T]!=0x3f3f3f3f;
}
int dfs(int x,int Cap)
{
    if(x==T)
    {
        return Cap;
    }
    if(!Cap)
    {
        return 0;
    }
    //cerr<<x<<endl;
    int Used=0;
    for(int i=arc[x];i;i=edge[i].nxt)
    {
        arc[x]=i;
        int v=edge[i].to;
        int w=edge[i].val;
        if(!w)
        {
            continue;
        }
        if(dis[v]==dis[x]+1)
        {
            int cap=dfs(v,min(Cap,w));
            edge[i].val-=cap;
            edge[i^1].val+=cap;
            Used+=cap;
            Cap-=cap;
            if(Cap==0)
            {
                break;
            }
        }
    }
    return Used;
}
int dinic()
{
    int Maxflow=0;
    while(bfs())
    {
        int Flow=0;
        while((Flow=dfs(S,INF)))
        {
            //cerr<<"fuc"<<endl;
            Maxflow+=Flow;
        }
    }
    return Maxflow;
}
int n,m;
int A[55];
int C[55];
int L[55][55];
signed main()
{
    //freopen("date.in","r",stdin);
    //freopen("date.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&C[i]);
    }
    int Res=0;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&A[i]);
        Res+=A[i];
    }
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&L[i][j]);
        }
    }
    S=0;
    for(int i=1;i<=n;i++)
    {
        add(S,i,INF);
        for(int j=1;j<=4;j++)
        {
            add((j-1)*n+i,j*n+i,(j-1)*C[i]);
        }
        
    }
    
    for(int i=1;i<=m;i++)
    {
        add(S,i+5*n,A[i]);
        for(int j=1;j<=n;j++)
        {
            add(i+5*n,(L[i][j]-1)*n+j,INF);
        }
    }
    T=5*n+m+1;
    for(int i=1;i<=n;i++)
    {
        add(i+4*n,T,4*C[i]);
    }

    // for(int i=0;i<=T;i++)
    // {
    //     for(int j=head[i];j;j=edge[j].nxt)
    //     {
    //         printf("%d %d %d\n",i,edge[j].to,edge[j].val);
    //     }
    // }
    printf("%d\n",Res-dinic());


}

ABC271Ex

恶心的分类讨论

Show Code
// LUOGU_RID: 132242047
#include<bits/stdc++.h>
using namespace std;
int Abs(int x)
{
    return x>0?x:-x;
}
int T;
int zfx[9]={1,1,0,-1,-1,-1,0,1};////
int zfy[9]={0,1,1,1,0,-1,-1,-1};
int rfx[9];////
int rfy[9];
int x,y;
string s;

signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&x,&y);
        
        cin>>s;
        if(x==0&&y==0)
        {
            printf("%d\n",0);
            continue;    
        }
        for(int i=0;i<8;i++)
        {
            rfx[i]=zfx[i];
            rfy[i]=zfy[i];
        }
        if(x<0)
        {
            for(int i=0;i<8;i++)
            {
                rfx[i]*=-1;
            }
            x=-x;
        }
        if(y<0)
        {
            for(int i=0;i<8;i++)
            {
                rfy[i]*=-1;
            }
            y=-y;
        }
        bool f1=0,f2=0,f3=0,f4=0;

        for(int i=0;i<8;i+=2)
        {
            if(s[i]=='1')
            {
                if(rfx[i]==1)
                {
                    f1=1;
                }
                else if(rfy[i]==1)
                {
                    f2=1;
                }
                else if(rfx[i]==-1)
                {
                    f3=1;
                }
                else if(rfy[i]==-1)
                {
                    f4=1;
                }
            }
        }

        long long Res=3e9+1;
        for(int i=0;i<8;i++)
        {
            if(s[i]=='1')
            {
                if((i&1))
                {
                    if(rfx[i]==1&&rfy[i]==1)
                    {
                        if(x==y)
                        {
                            Res=min(Res,1ll*x);
                        }
                    }
                }
                else
                {
                    if(rfx[i]==1)
                    {
                        if(y==0)
                        {
                            Res=min(Res,1ll*x);
                        }
                    }
                    else if(rfy[i]==1)
                    {
                        if(x==0)
                        {
                            Res=min(Res,1ll*y);
                        }
                    }
                }
            }            

            
            for(int j=0;j<8;j++)
            {
                if(i==j)
                {
                    continue;
                }
                if(rfx[i]==-1&&rfy[i]==-1)
                {
                    continue;
                }
                if(rfx[j]==-1&&rfy[j]==-1)
                {
                    continue;
                }

                if(s[i]=='1'&&s[j]=='1')
                {
                    if((i&1)&&(j&1))
                    { 
                        if((rfx[i]==1&&rfy[i]==1))
                        {
                            //printf("fuckfucf???\n");
                            if(x>=y&&(rfy[j]==-1)&&((x+y)%2==0))
                            {
                                Res=min(Res,(long long)x);
                            }
                            else if(x>=y&&(rfy[j]==-1))
                            {
                                if(f2||f4)
                                {
                                    Res=min(Res,(long long)x+1);
                                }
                                if(f1)
                                {
                                    Res=min(Res,(long long)x);
                                }
                                if(f3)
                                {
                                    Res=min(Res,(long long)x+2);    
                                }
                            }

                            else if(x<=y&&(rfx[j]==-1)&&((x+y)%2==0))
                            {
                                Res=min(Res,(long long)y);
                            }
                            else if(x<=y&&(rfx[j]==-1))
                            {
                                if(f1||f3)
                                {
                                    Res=min(Res,(long long)y+1);
                                }
                                if(f2)
                                {
                                    Res=min(Res,(long long)y);
                                }
                                if(f4)
                                {
                                    Res=min(Res,(long long)y+2);    
                                }
                                
                            }
                        }
                        if((rfx[j]==1&&rfy[j]==1))
                        {
                            swap(i,j);
                            if(x>=y&&(rfy[j]==-1)&&((x+y)%2==0))
                            {
                                Res=min(Res,(long long)x);
                            }
                            else if(x>=y&&(rfy[j]==-1))
                            {
                                if(f2||f4)
                                {
                                    Res=min(Res,(long long)x+1);
                                }
                                if(f1)
                                {
                                    Res=min(Res,(long long)x);
                                }
                                if(f3)
                                {
                                    Res=min(Res,(long long)x+2);    
                                }
                            }

                            else if(x<=y&&(rfx[j]==-1)&&((x+y)%2==0))
                            {
                                Res=min(Res,(long long)y);
                            }
                            else if(x<=y&&(rfx[j]==-1))
                            {
                                if(f1||f3)
                                {
                                    Res=min(Res,(long long)y+1);
                                }
                                if(f2)
                                {
                                    Res=min(Res,(long long)y);
                                }
                                if(f4)
                                {
                                    Res=min(Res,(long long)y+2);    
                                }
                                
                            }
                            swap(i,j);
                        }
                    }
                    else if((i%2==0)&&(j%2==0))
                    {   
                        if(rfx[i]==1&&rfy[j]==1)
                        {
                            Res=min(Res,(long long)x+y);
                        }           
                        if(rfy[i]==1&&rfx[j]==1)
                        {
                            Res=min(Res,(long long)x+y);
                        }    
                    }
                    else if(i&1)
                    {
                        if(rfx[i]==-1&&rfy[i]==1)
                        {
                            if(rfx[j]==1)
                            {
                                Res=min(Res,2ll*y+x);
                            }
                        }

                        if(rfx[i]==1&&rfy[i]==1)
                        {
                            if(rfx[j]==1&&(x>=y))
                            {
                                Res=min(Res,1ll*x);
                            }
                            if(rfy[j]==-1&&(x>=y))
                            {
                                Res=min(Res,1ll*x+(x-y));
                            }
                            if(rfx[j]==-1&&(x<=y))
                            {
                                Res=min(Res,1ll*y+(y-x));
                            }
                            if(rfy[j]==1&&(x<=y))
                            {
                                Res=min(Res,1ll*y);
                            }
                        }
                        if(rfx[i]==1&&rfy[i]==-1)
                        {
                            if(rfy[j]==1)
                            {
                                Res=min(Res,2ll*x+y);
                            }
                        }

                    }
                    else if(j&1)
                    {
                        swap(i,j);
                        if(rfx[i]==-1&&rfy[i]==1)
                        {
                            if(rfx[j]==1)
                            {
                                Res=min(Res,2ll*y+x);
                            }
                        }

                        if(rfx[i]==1&&rfy[i]==1)
                        {
                            if(rfx[j]==1&&(x>=y))
                            {
                                Res=min(Res,1ll*x);
                            }
                            if(rfy[j]==-1&&(x>=y))
                            {
                                Res=min(Res,1ll*x+(x-y));
                            }
                            if(rfx[j]==-1&&(x<=y))
                            {
                                Res=min(Res,1ll*y+(y-x));
                            }
                            if(rfy[j]==1&&(x<=y))
                            {
                                Res=min(Res,1ll*y);
                            }
                        }
                        if(rfx[i]==1&&rfy[i]==-1)
                        {
                            if(rfy[j]==1)
                            {
                                Res=min(Res,2ll*x+y);
                            }
                        }
                        swap(i,j);
                    }
                }
            }
        }

        
        if(Res==3e9+1)
        {
            printf("-1\n");
        }
        else
        {
            printf("%lld\n",Res);
        }
    }    

}

ABC270G

\(BSGS\)半屉

Show Code
#include<bits/stdc++.h>
using namespace std;
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int t;
int P,A,B,S,G;
map<int,int>Vis;
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d %d %d %d",&P,&A,&B,&S,&G);
        if(A==0)
        {
            if(S==G)
            {
                printf("0\n");
            }
            else if(B==G)
            {
                printf("1\n");
            }
            else{
                printf("-1\n");
            }
        }
        else if(A==1)
        {
            if(S==G)
            {
                printf("0\n");
            }
            else 
            {
                int det=((long long)G-S+P)%P;
                det=((long long)det*inv(B,P))%P;
                printf("%d\n",det);  
            }
        }
        else
        {
            Vis.clear();
            B=((long long)B*inv(A-1,P))%P;
            G=((long long)G+B)%P;
            S=((long long)S+B)%P;
            G=((long long)G*inv(S,P))%P;
            //printf("%d %d???\n",A,G);
            int Lit=sqrt(P);
            int Mul=1;
            Vis[1]=0;
            for(int i=1;i<=Lit;i++)
            {
                Mul=((long long)Mul*A)%P;
                if(i<Lit)
                {
                    if(Vis.find(Mul)==Vis.end())
                    {
                        Vis[Mul]=i;
                    }
                }
            }
            int Km=Mul;
            int Res=0x3f3f3f3f;
            Mul=1;
            for(int i=0;i<=Lit;i++)
            {
                int lk=((long long)G*inv(Mul,P))%P;
                if(Vis.find(lk)!=Vis.end())
                {
                    Res=min(Res,i*Lit+Vis[lk]);
                }
                Mul=((long long)Mul*Km)%P;
            }
            if(Res==0x3f3f3f3f)
            {
                printf("-1\n");
            }
            else
            {
                printf("%d\n",Res);
            }
        }
    }
    

}

ABC269G

背包种类数只有\(\sqrt m\)

原因是考虑\(\sum|A_i-B_i|\le m\),这是经典结构

然后就单调队列多重背包,负的和正的分开算即可

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+5;

int n;
int M;
int A[MAXN];
int B[MAXN];
map<int,int>D;
int dp[MAXN*2];
int dq[MAXN];
int tmp[MAXN*2];
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&M);
    int Suma=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d",&A[i],&B[i]);
        D[B[i]-A[i]]++;
        Suma+=A[i];
    }
    
    vector<pair<int,int> >V;
    for(auto it=D.begin();it!=D.end();it++)
    {
        V.push_back((*it));
        //printf("%d %d???\n",(*it).first,(*it).second);
    }
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    int Key=0;
    sort(V.begin(),V.end());
    for(int i=0;i<V.size();i++)
    {
        int Lit=V[i].second;
        int c=V[i].first;
        for(int j=0;j<=2*M;j++)
        {
            tmp[j]=dp[j];
        }
        if(c<0)
        {
            c=-c;  
            for(int j=0;j<c;j++)
            {
                int head=1;
                int tail=0;
                dq[++tail]=0;
                for(int k=1;j+k*c<=M;k++)
                {
                    while(head<=tail&&k-dq[head]>Lit)
                    {
                        head++;
                    }
                    dp[j+k*c]=min(dp[j+k*c],tmp[j+dq[head]*c]+(k-(dq[head])));
                    while(head<=tail&&tmp[j+k*c]-k<=tmp[j+dq[tail]*c]-dq[tail])
                    {
                        tail--;
                    }
                    dq[++tail]=k;
                }   
            }
            //printf("%d %d::\n",c,dp[2]);
        }
        else if(c>0)
        {
            Key=i;
            break;
        }
    }
    memset(tmp,0x3f,sizeof(tmp));
    for(int i=0;i<=M;i++)
    {
        tmp[M-i]=dp[i];
        //printf("%d %d:\n",i,dp[i]);
    }
    for(int i=0;i<=2*M;i++)
    {
        dp[i]=tmp[i];
     //   printf("%d %d:\n",i,dp[i]);
    }
    for(int i=Key;i<V.size();i++)
    {
        int Lit=V[i].second;
        int c=V[i].first;
        for(int j=0;j<=2*M;j++)
        {
            tmp[j]=dp[j];
        }
        for(int j=0;j<c;j++)
        {
            int head=1;
            int tail=0;
            dq[++tail]=0;
            for(int k=1;j+k*c<=2*M;k++)
            {
                while(head<=tail&&k-dq[head]>Lit)
                {
                    head++;
                }
                dp[j+k*c]=min(dp[j+k*c],tmp[j+dq[head]*c]+(k-(dq[head])));
                while(head<=tail&&tmp[j+k*c]-k<=tmp[j+dq[tail]*c]-dq[tail])
                {
                    tail--;
                }
                dq[++tail]=k;
            }   
        }
    }
    // printf("------\n");
    // for(int i=0;i<=2*M;i++)
    // {
    //     printf("%d %d:\n",i,dp[i]);
    // }
    for(int i=0;i<=M;i++)
    {
        int Rg=dp[i-Suma+M];
        if(Rg==0x3f3f3f3f)
        {
            printf("-1\n");
        }
        else
        {
            printf("%d\n",Rg);
        }

    }
    
}

ABC217Ex

\(dp_i=\frac{\sum\limits_{i=1}^ndp_{\max i-1,A_i}}{n}+1\)

\(c_i\)\(\sum\limits_{j=1}^n[A_j< i]\)的数量

\(dp_i=\frac{dp_{i-1}c_i}{n}+\frac{\sum\limits_{j=c_i+1}^ndp_j}{n}+1\)

\(dp_{i-1}=\frac{n}{c_i}dp_i-\frac{n}{c_i}1-\frac{\sum\limits_{j=c_i+1}^ndp_j}{c_i}\)

然后主元\(+\)矩阵

Show Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=998244353;
const int MAXN=2e5+5;
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int n;
long long a[MAXN];
long long b[MAXN];
pair<int,int>dp[MAXN];
pair<int,int>operator+(const pair<int,int>x,const pair<int,int>y)
{
    return make_pair(((long long)x.first+y.first)%MOD,((long long)x.second+y.second)%MOD);
}
pair<int,int>operator*(const pair<int,int>x,const pair<int,int> y)
{
    return make_pair((((long long)x.first*y.second)%MOD+((long long)y.first*x.second)%MOD)%MOD,((long long)x.second*y.second)%MOD);
}
struct Martix{
    pair<int,int>val[2][2];
    void clear()
    {
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<2;j++)
            {
                val[i][j]=make_pair(0,0);
            }
        }
    }
    void init()
    {
        clear();
        for(int i=0;i<2;i++)
        {
            val[i][i]=make_pair(0,1);
        }
    }

    void print()
    {
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<2;j++)
            {
                printf("(%lld,%lld) ",val[i][j].first,val[i][j].second);
            }
            printf("\n");
        }
    }
    Martix operator*(const Martix x)const{
        Martix Res;
        Res.clear();
        for(int k=0;k<2;k++)
        {
            for(int i=0;i<2;i++)
            {
                for(int j=0;j<2;j++)
                {
                    Res.val[i][j]=Res.val[i][j]+val[i][k]*x.val[k][j];
                }
            }
        }
        return Res;
    }
};
Martix Pw(Martix Base,long long b)
{
    Martix res;
    res.init();
    while(b)
    {
        if(b&1)
        {
            res=res*Base;
        }
        Base=Base*Base;
        b>>=1;
    }
    return res;
}
map<long long,int>V;
signed main()
{
    freopen("date.in","r",stdin);
    freopen("date.out","w",stdout);
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        b[i]=a[i];
        V[a[i]]++;
    }
    int Cnt=unique(b+1,b+1+n)-b-1;
    dp[Cnt]=make_pair(1,0);
    pair<int,int>Pre=dp[Cnt]*make_pair(0,V[b[Cnt]]);
    for(int i=Cnt-1;i>=1;i--)
    {
        long long Times=(b[i+1]-b[i]);
        int c=lower_bound(a+1,a+1+n,b[i+1])-a-1;
       // printf("%lld %lld %lld %lld??\n",Pre.first,Pre.second,c,Times);
        Martix A,B;
        A.clear();
        A.val[0][0]=dp[i+1];
        A.val[0][1]=make_pair(0,1);
        B.val[0][0]=make_pair(0,((long long)n*inv(c,MOD))%MOD);
        B.val[1][1]=make_pair(0,1);
        B.val[1][0]=make_pair(0,((long long)n*inv(c,MOD))%MOD)+make_pair(0,inv(c,MOD))*Pre;
        B.val[1][0].first=(MOD-B.val[1][0].first)%MOD;
        B.val[1][0].second=(MOD-B.val[1][0].second)%MOD;
        B=Pw(B,Times);
        A=A*B;
        dp[i]=A.val[0][0];
        Pre=Pre+dp[i]*make_pair(0,V[b[i]]);
    }
    int Res=(((long long)MOD-dp[1].second)*inv(dp[1].first,MOD))%MOD;
    printf("%lld\n",Res);
}

ABC268G

被诈骗了/kk

最开始没看出来,实际上两个串如果不是前后缀关系,则对于它们的先后关系是随机的,即\(j\)\(i\)的贡献为\(\dfrac{1}{2}\)

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=5e5+5;
int n,m;
string S[MAXN];
int Tree[MAXN][27];
int cnt_node;
int Num1[MAXN];
int Num2[MAXN];
void Insert(string s)
{
    int p=0;
    for(int i=0;i<s.size();i++)
    {
        if(!Tree[p][s[i]-'a'])
        {
            Tree[p][s[i]-'a']=++cnt_node;
        }
        
        p=Tree[p][s[i]-'a'];
    }
    Num1[p]++;
    Num2[p]++;
}
void dfs(int p)
{
    for(int i=0;i<26;i++)
    {
        if(Tree[p][i])
        {
            dfs(Tree[p][i]);
            Num2[p]+=Num2[Tree[p][i]];
        }
    }
}
int inv2=MOD-MOD/2;
int Query(string x)
{
    int p=0;
    int a=0;
    for(int i=0;i<x.size();i++)
    {
        p=Tree[p][x[i]-'a'];
        a+=Num1[p];
    }
    int b=Num2[p];
    //printf("%d %d\n",a,b);
    return (((long long)n-a-b+1)*inv2+a)%MOD;
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>S[i];
        Insert(S[i]);
    }
    dfs(0);
    for(int i=1;i<=n;i++)
    {
        printf("%d\n",Query(S[i]));
    }
}   

ABC268Ex

AC自动机板子

Show Code
// LUOGU_RID: 132443105
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e5+5;
int n,m;
int Tree[MAXN][27];////
int Num[MAXN];
int cnt_node;////
void Insert(string x)
{
    int p=0;
    for(int i=0;i<x.size();i++)
    {   
        if(!Tree[p][x[i]-'a'+1])
        {
            Tree[p][x[i]-'a'+1]=++cnt_node;
        }
        p=Tree[p][x[i]-'a'+1];
    }
    Num[p]++;
}
void ACAM()
{
    queue<int>q;
    for(int i=1;i<=26;i++)
    {
        if(Tree[0][i])
        {
            q.push(Tree[0][i]);
        }
    }
    while(q.size())
    {
        int temp=q.front();
        //cerr<<temp<<endl;
        q.pop();
        for(int i=1;i<=26;i++)
        {
            if(Tree[temp][i])
            {
                q.push(Tree[temp][i]);
                Tree[Tree[temp][i]][0]=Tree[Tree[temp][0]][i];
            }
            else
            {
                Tree[temp][i]=Tree[Tree[temp][0]][i];
            }
        }
    }
}
vector<int>g[MAXN];
string S,T;
void dfs(int x)
{
    for(int i=0;i<g[x].size();i++)
    {
        int v=g[x][i];
        Num[v]+=Num[x];
        dfs(v);
    }
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    cin>>S;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>T;
        Insert(T);
    }
    //cerr<<"fuck"<<endl;
    ACAM();
    
    for(int i=1;i<=cnt_node;i++)
    {
        g[Tree[i][0]].push_back(i);
    }
    dfs(0);
    int p=0;
    int Res=0;
    for(int i=0;i<S.size();i++)
    {
        p=Tree[p][S[i]-'a'+1];
        if(Num[p])
        {
            p=0;
            ++Res;
        }
    }
    printf("%d\n",Res);
}   

ABC267G

简单\(dp\),最开始把值相同的合并成一段,结果搞出来个\(n^3\)

其实直接算就行了

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=5005;
int n,k;
int a[MAXN];
int Same[MAXN];
int dp[MAXN][MAXN];
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    sort(a+1,a+1+n);
    dp[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=i;j++)
        {
            if(dp[i-1][j])
            {
                dp[i][j]=((long long)dp[i][j]+((long long)dp[i-1][j]*(Same[a[i]]+j+1))%MOD)%MOD;
                dp[i][j+1]=((long long)dp[i][j+1]+((long long)dp[i-1][j]*(i-Same[a[i]]-j-1))%MOD)%MOD;
            }
        }
        Same[a[i]]++;
    }
    printf("%d\n",dp[n][k]);   
}

ABC267Ex

NTT板子

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int g=3;
const int MAXN=1e6+5;///
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {///
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int rev[MAXN*2];
struct Poly{
    vector<int>V;
    void NTT(int Lit,int op)
    {
        while(V.size()<(1<<Lit))
        {//
            V.push_back(0);
        }
        for(int i=0;i<(1<<Lit);i++)
        {
            rev[i]=(rev[i>>1]>>1)|(i&1)<<(Lit-1);
        }
        for(int i=0;i<(1<<Lit);i++)
		{
			if(i<rev[i])
			{
				swap(V[i],V[rev[i]]);
			}
		}
        for(int len=1;len<(1<<Lit);len<<=1)
        {
            int w=Pow(g,(MOD-1)/(len<<1),MOD);
            if(op==-1)
            {
                w=inv(w,MOD);
            }
            for(int i=0;i<(1<<Lit);i+=(len<<1))
            {
                for(int j=i,wn=1;j<(i+len);j++,wn=((long long)wn*w)%MOD)
                {
                    int x=V[j];
                    int y=V[j+len];
                    V[j]=((long long)x+((long long)y*wn)%MOD)%MOD;
                    V[j+len]=((long long)x-((long long)y*wn)%MOD+MOD)%MOD;
                }
            }
        }
        if(op==-1)
        {
            int mkx=inv((1<<Lit),MOD);
            for(int i=0;i<(1<<Lit);i++)
            {
                V[i]=((long long)V[i]*mkx)%MOD;
            }
        }
    }
};
Poly Mul(Poly x,Poly y)
{
    int N=x.V.size();
    int M=y.V.size();
    int C=N+M-1;
    while(x.V.size()<C)
    {
        x.V.push_back(0);
    }
    while(y.V.size()<C)
    {
        y.V.push_back(0);
    }
    int nx=1;
    int nox=0;
    while(nx<C)
    {
        nx<<=1;
        nox++;
    }
    x.NTT(nox,1);
    y.NTT(nox,1);
    for(int i=0;i<(1<<nox);i++)
    {
        x.V[i]=((long long)x.V[i]*y.V[i])%MOD;
    }
    x.NTT(nox,-1);
    while(x.V.size()>C)
    {
        x.V.pop_back();
    }
    return x;
}

int n;
int A[MAXN];
int Ct[15];
int fac[MAXN];
int inv_fac[MAXN];
int C(int n,int m)
{
    if(n<m||m<0)
    {
        return 0;
    }
    if((n==m)||(m==0))
    {
        return 1;
    }
    return ((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD;
}
int m;
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    fac[0]=1;
    for(int i=1;i<=MAXN-5;i++)
    {
        fac[i]=((long long)fac[i-1]*i)%MOD;
    }
    inv_fac[MAXN-5]=inv(fac[MAXN-5],MOD);
    for(int i=MAXN-5-1;i>=1;i--)
    {
        inv_fac[i]=((long long)inv_fac[i+1]*(i+1))%MOD;
    }
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&A[i]);
        Ct[A[i]]++;
    }
    Poly F,G;
    F.V.resize(1,1);
    G.V.resize(1,1);
    for(int i=1;i<=10;i++)
    {
        Poly A,B;
        A.V.resize((Ct[i]+1)*i,0);
        B.V.resize((Ct[i]+1)*i,0);
        for(int j=0;j<=Ct[i];j++)
        {
            A.V[j*i]=C(Ct[i],j);
            B.V[j*i]=C(Ct[i],j);
            if(j&1)
            {
                B.V[j*i]=(MOD-B.V[j*i]);
            }
        }
        F=Mul(F,A);
        G=Mul(G,B);
    }
    
    int inv2=(MOD-MOD/2);
    if(F.V.size()<=m)
    {
        printf("0\n");
    }
    else
    {
        int zhmnb=(F.V[m]-G.V[m]+MOD)%MOD;
        zhmnb=((long long)zhmnb*inv2)%MOD;
        printf("%d\n",zhmnb);
    }
}

ABC266Ex

CDQ板子

Show Code
#include<bits/stdc++.h>
#define ls Tree[p].lc
#define rs Tree[p].rc
using namespace std;
const int MAXN=1e5+5;
int n;
struct node{
	int t,x,y,v;
	int ind;
}a[MAXN],tmp[MAXN];
bool cmp(node x,node y)
{
	if(x.y==y.y)
	{
		return x.t<y.t;
	}
	return x.y<y.y;
}
bool kmp(node x,node y)
{
	return x.t-x.y-x.x<y.t-y.y-y.x;
}
long long dp[MAXN];
struct Seg{
	long long date;
	int lc,rc;
}Tree[MAXN*10];
int cnt_node;
int rt;
int New()
{
	++cnt_node;
	Tree[cnt_node].lc=Tree[cnt_node].rc=0;
	Tree[cnt_node].date=0;
	return cnt_node;
}
void Insert(int &p,int l,int r,int k,long long x)
{
	if(!p)
	{
		p=New();
	}
	Tree[p].date=max(Tree[p].date,x);
	if(l==r)
	{
		return;
	}
	int mid=((long long)l+r)>>1;
	if(k<=mid)
	{
		Insert(ls,l,mid,k,x);
	}
	else
	{
		Insert(rs,mid+1,r,k,x);
	}
}
long long Query(int p,int l,int r,int ql,int qr)
{
	if(!p)
	{
		return 0;
	}
	if(l>=ql&&r<=qr)
	{
		return Tree[p].date;
	}
	int mid=((long long)l+r)>>1;
	long long Res=0;
	if(ql<=mid)
	{
		Res=max(Res,Query(ls,l,mid,ql,qr));
	}
	if(qr>mid)
	{
		Res=max(Res,Query(rs,mid+1,r,ql,qr));
	}
	return Res;
}

void solve(int l,int r)
{
	if(l==r)
	{
		return;
	}
	int mid=(l+r)>>1;
	solve(l,mid);
	int pl=l,pr=mid+1;
	cnt_node=0;
	rt=0;
	for(int i=l;i<=r;i++)
	{
		tmp[i]=a[i];
	}
	sort(a+l,a+mid+1,kmp);
	sort(a+mid+1,a+r+1,kmp);
	//printf("%d %d----\n",l,r);
	while(pl<=mid&&pr<=r)
	{
		if(a[pl].t-a[pl].y-a[pl].x<=a[pr].t-a[pr].y-a[pr].x)
		{
			Insert(rt,-2e9,2e9,a[pl].t-a[pl].y+a[pl].x,dp[a[pl].ind]);
		//	printf("%d %d:::\n",a[pl].ind,a[pl].t-a[pl].y+a[pl].x);
			pl++;	
		}
		else
		{	
			dp[a[pr].ind]=max(dp[a[pr].ind],Query(rt,-2e9,2e9,-2e9,a[pr].t-a[pr].y+a[pr].x)+a[pr].v);
		//	printf("%d %d:::\n",a[pr].ind,a[pr].t-a[pr].y+a[pr].x);
			pr++;
		}
	}
	while(pl<=mid)
	{
		Insert(rt,-2e9,2e9,a[pl].t-a[pl].y+a[pl].x,dp[a[pl].ind]);	
		//printf("%d %d:::\n",a[pl].ind,a[pl].t-a[pl].y+a[pl].x);
		pl++;
	}
	while(pr<=r)
	{
		dp[a[pr].ind]=max(dp[a[pr].ind],Query(rt,-2e9,2e9,-2e9,a[pr].t-a[pr].y+a[pr].x)+a[pr].v);
		//printf("%d %d:::\n",a[pr].ind,a[pr].t-a[pr].y+a[pr].x);
		pr++;
	}
	for(int i=l;i<=r;i++)
	{
		a[i]=tmp[i];
	}
	solve(mid+1,r);
}
int main()
{
	// freopen("date.in","r",stdin);
	// freopen("date.out","w",stdout);
	scanf("%d",&n);
	if(n==1||n==0)
	{
		printf("0\n");
		return 0;
	}
	
	bool f=1;
	for(int i=1;i<=n;i++)
	{
		scanf("%d %d %d %d",&a[i].t,&a[i].x,&a[i].y,&a[i].v);
		
		a[i].ind=i;
		dp[i]=-1e18;
		if(a[i].t==0&&a[i].x==0&&a[i].y==0)
		{
			f=0;
			dp[i]=a[i].v;
		}
	}
	if(f)
	{
		a[++n]=(node){0,0,0,0,0};
		dp[0]=0;
	}
	
	sort(a+1,a+1+n,cmp);
	solve(1,n);
	long long Res=0;
	for(int i=0;i<=n;i++)
	{
		Res=max(Res,dp[i]);
	}
	printf("%lld\n",Res);
	// for(int i=0;i<n;i++)
	// {
	// 	printf("%d\n",dp[i]);
	// }
}

ABC265G

线段树半屉

Show Code
#include<bits/stdc++.h>
#define ls p<<1
#define rs (p<<1)|1
using namespace std;
const int MAXN=1e5+5;
struct Date{
    int date[3];
    long long res[3][3];
};
struct Seg{
    Date d;
    int lazy[3];
    int l,r;
}Tree[MAXN*4];
int tmpr[3][3];
int tmpd[3];
Date Merge(Date x,Date y)
{
    Date res;
    for(int i=0;i<=2;i++)
    {
        res.date[i]=x.date[i]+y.date[i];
    }
    for(int i=0;i<=2;i++)
    {
        for(int j=0;j<=2;j++)
        {
            res.res[i][j]=x.res[i][j]+y.res[i][j];
        }
    }
    for(int i=0;i<=2;i++)
    {
        for(int j=0;j<=2;j++)
        {
            res.res[i][j]+=((long long)x.date[i]*y.date[j]);
        }
    }
    return res;
}
void push_up(int p)
{
    Tree[p].d=Merge(Tree[ls].d,Tree[rs].d);
}
void push_down(int p)
{
    if(Tree[p].lazy[0]!=-1)
    {
        for(int i=0;i<=2;i++)
        {
            tmpd[i]=Tree[ls].d.date[i];
            Tree[ls].d.date[i]=0;
            for(int j=0;j<=2;j++)
            {
                tmpr[i][j]=Tree[ls].d.res[i][j];
                Tree[ls].d.res[i][j]=0;
            }
        }

        for(int i=0;i<=2;i++)
        {
            Tree[ls].d.date[Tree[p].lazy[i]]+=tmpd[i];
            for(int j=0;j<=2;j++)
            {
                Tree[ls].d.res[Tree[p].lazy[i]][Tree[p].lazy[j]]+=tmpr[i][j];    
            }
        }

        if(Tree[ls].lazy[0]==-1)
        {
            for(int i=0;i<=2;i++)
            {
                Tree[ls].lazy[i]=Tree[p].lazy[i];
            }
        }
        else
        {
            for(int i=0;i<=2;i++)
            {
                Tree[ls].lazy[i]=Tree[p].lazy[Tree[ls].lazy[i]];
            }
        }
        for(int i=0;i<=2;i++)
        {
            tmpd[i]=Tree[rs].d.date[i];
            Tree[rs].d.date[i]=0;
            for(int j=0;j<=2;j++)
            {
                tmpr[i][j]=Tree[rs].d.res[i][j];
                Tree[rs].d.res[i][j]=0;
            }
        }

        for(int i=0;i<=2;i++)
        {
            Tree[rs].d.date[Tree[p].lazy[i]]+=tmpd[i];
            for(int j=0;j<=2;j++)
            {
                Tree[rs].d.res[Tree[p].lazy[i]][Tree[p].lazy[j]]+=tmpr[i][j];    
            }
        }
        if(Tree[rs].lazy[0]==-1)
        {
            for(int i=0;i<=2;i++)
            {
                Tree[rs].lazy[i]=Tree[p].lazy[i];
            }
        }
        else
        {
            for(int i=0;i<=2;i++)
            {
                Tree[rs].lazy[i]=Tree[p].lazy[Tree[rs].lazy[i]];
            }
        }
        Tree[p].lazy[0]=-1;
    }
}
int n;
int a[MAXN];
void Build(int p,int l,int r)
{
    Tree[p].l=l;
    Tree[p].r=r;
    Tree[p].lazy[0]=-1;
    if(l==r)
    {
        Tree[p].d.date[a[l]]=1;
        return;
    }
    int mid=(l+r)>>1;
    Build(ls,l,mid);
    Build(rs,mid+1,r);
    push_up(p);
}

void Update(int p,int l,int r,vector<int>Lazy)
{
    if(Tree[p].l>=l&&Tree[p].r<=r)
    {
        for(int i=0;i<=2;i++)
        {
            tmpd[i]=Tree[p].d.date[i];
            Tree[p].d.date[i]=0;
            for(int j=0;j<=2;j++)
            {
                tmpr[i][j]=Tree[p].d.res[i][j];
                Tree[p].d.res[i][j]=0;
            }
        }

        for(int i=0;i<=2;i++)
        {
            Tree[p].d.date[Lazy[i]]+=tmpd[i];
            for(int j=0;j<=2;j++)
            {
                Tree[p].d.res[Lazy[i]][Lazy[j]]+=tmpr[i][j];    
            }
        }

        if(Tree[p].lazy[0]==-1)
        {
            for(int i=0;i<=2;i++)
            {
                Tree[p].lazy[i]=Lazy[i];
            }
        }
        else
        {
            for(int i=0;i<=2;i++)
            {
                Tree[p].lazy[i]=Lazy[Tree[p].lazy[i]];
            }
        }
        return;
    }
    int mid=(Tree[p].l+Tree[p].r)>>1;
    push_down(p);
    if(l<=mid)
    {
        Update(ls,l,r,Lazy);
    }
    if(r>mid)
    {
        Update(rs,l,r,Lazy);
    }
    push_up(p);
}
Date Query(int p,int l,int r)
{
    if(Tree[p].l>=l&&Tree[p].r<=r)
    {
        return Tree[p].d;
    }
    push_down(p);
    int mid=(Tree[p].l+Tree[p].r)>>1;
    if(l<=mid&&r>mid)
    {
        return Merge(Query(ls,l,r),Query(rs,l,r));
    }
    else if(l<=mid)
    {
        return Query(ls,l,r);
    }
    else
    {
        return Query(rs,l,r);
    }
}
int q,op,l,r,x,y,z;
int main()
{
	// freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    Build(1,1,n);
    while(q--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d %d",&l,&r);
            Date Rk=Query(1,l,r);
            long long Res=0;
            for(int i=0;i<=2;i++)
            {
                for(int j=0;j<i;j++)
                {
                    Res+=Rk.res[i][j];
                }
            }
            printf("%lld\n",Res);
        }
        else
        {
            scanf("%d %d %d %d %d",&l,&r,&x,&y,&z);
            vector<int>Krp;
            Krp.clear();
            Krp.push_back(x);
            Krp.push_back(y);
            Krp.push_back(z);
            Update(1,l,r,Krp);
        }
    }
}

ABC264G

Spfa半屉

Show Code
#include<bits/stdc++.h>
using namespace std;
int n;
string a,b;
int P[200005];
int Hash(string s)
{
    int H=0;
    for(int i=0;i<s.size();i++)
    {
        H=H*27+(s[i]-'a'+1);
    }
    return H;
}
vector<pair<int,long long> >g[200005];
long long dp[200005];
int rd[200005];
int vis[200005];
int tot[200005];
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    while(n--)
    {
        cin>>a;
        scanf("%d",&P[Hash(a)]);
    }
    for(int i=0;i<=26;i++)
    {
        for(int j=0;j<=26;j++)
        {
            a.clear();
            if(i)
            {
                a+=i-1+'a';
            }
            if(j)
            {
                a+=j-1+'a';
            }

            if(a.size())
            {
                for(int k=1;k<=26;k++)
                {   
                    string b=a+(char)(k+'a'-1);
                    long long Tmp=0;
                    for(int l=0;l<b.size();l++)
                    {
                        int H=0;
                        for(int r=l;r<b.size();r++)
                        {
                            H=H*27+(b[r]-'a'+1);
                            if(r==b.size()-1)
                            {
                                Tmp+=P[H];
                            }
                        }
                    }
                   // cout<<a<<" "<<b<<" "<<Tmp<<endl;
                   if(b.size()>=3)
                   {
                    b.erase(b.begin(),b.begin()+1);
                   }
                    
                    g[Hash(a)].push_back(make_pair(Hash(b),Tmp));
                //    cout<<a<<" "<<b<<" "<<Tmp<<" "<<endl;
                //    if(Hash(b)==82)
                //    {
                //         cout<<b<<" "<<"djiijsfssfjkskfjksfkjsk"<<endl;
                //    }
                //    if(Hash(a)==82)
                //    {
                //         cout<<a<<" "<<"djiijsfssfjkskfjksfkjsk"<<endl;
                //    }
                }
            }
        }
    }
    string NYH="z";
    NYH+='z';
    NYH+='z';
    int Cnt=Hash(NYH);
    memset(dp,-0x3f,sizeof(dp));
    for(int i=1;i<=26;i++)
    {
        g[0].push_back(make_pair(i,P[i]));
    }
    dp[0]=0;
    queue<int>q;
    q.push(0);
    while(q.size())
    {
        int temp=q.front();
        q.pop();
        vis[temp]=0;
    //    printf("%d %lld??\n",temp,dp[temp]);
        if(tot[temp]>Cnt)
        {
            printf("Infinity\n");
            return 0;
        }
        tot[temp]++;
        for(int i=0;i<g[temp].size();i++)
        {
            int v=g[temp][i].first;
            int w=g[temp][i].second;
            if(dp[v]<dp[temp]+w)
            {
                dp[v]=dp[temp]+w;
                // if(v==29)
                // {
                //     printf("%d %d %d----\n",v,dp[v],temp);
                // }
                if(vis[v])
                {
                    continue;
                }
                vis[v]=1;
                q.push(v);
            }
        }
    }   

    long long Res=-0x3f3f3f3f3f3f3f3f;
    for(int i=1;i<=Cnt;i++)
    {
        Res=max(Res,dp[i]);
        // if(dp[i]==10)
        // {
        //     printf("jdkf%d\n",i);
        // }
    }
    printf("%lld\n",Res);
    
}

ABC264Ex

简单Dp

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+5;
const int MOD=998244353;
int n;
int P[MAXN];
int dep[MAXN];
int dp[MAXN][21][2];
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&P[i]);
    }
    dep[1]=1;
    printf("%d\n",1);
    dp[1][1][2]=1;
    for(int i=2;i<=n;i++)
    {
        dep[i]=dep[P[i]]+1;
        if(dep[i]<=20)
        {
            dp[i][1][2]=1;
            int d=2;
            int Now=P[i];
            int Pre=i;
            int Pv=0;
            while(Now)
            {
                int Nv=dp[Now][d][2];
                dp[Now][d][1]=((long long)dp[Now][d][1]-Pv+MOD)%MOD;
                dp[Now][d][2]=((long long)dp[Now][d][2]-((long long)Pv*dp[Now][d][1])%MOD+MOD)%MOD;
                
                dp[Now][d][2]=((long long)dp[Now][d][2]+((long long)dp[Pre][d-1][2]*dp[Now][d][1])%MOD)%MOD;
                dp[Now][d][1]=((long long)dp[Now][d][1]+dp[Pre][d-1][2])%MOD;
                Pre=Now;
                Pv=Nv;
                Now=P[Now];
                d++;
            }

        }
        int Res=0;
        for(int j=1;j<=20;j++)
        {
            Res=((long long)Res+dp[1][j][2])%MOD;
        }
        printf("%d\n",Res);
    }
}

ABC263G

小丑<——

奇偶分类就是网络流,不过要特殊处理\(1\)

贪心得想就是先匹配不是\(1\)得再调整

这里直接在残余网络上跑即可

Show Code
#include<bits/stdc++.h>
#define INF 1e9
#define int long long
using namespace std;
const int MAXN=200005;
struct Edge{
    int val,to,nxt;
}edge[MAXN];
int head[MAXN];
int cnt_edge=1;
void Add(int u,int v,int val)
{
    ++cnt_edge;
    edge[cnt_edge].nxt=head[u];
    edge[cnt_edge].val=val;
    edge[cnt_edge].to=v;
    head[u]=cnt_edge;
    return;
}
void add(int u,int v,int val)
{
    Add(u,v,val);
    Add(v,u,0);
}
int S,T;
int arc[MAXN];
int dis[MAXN];
int bfs()
{
    memset(dis,0x3f,sizeof(dis));
    queue<int>q;
    dis[S]=0;
    q.push(S);
    while(q.size())
    {
        int u=q.front();
        arc[u]=head[u];
        q.pop();
        for(int i=head[u];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            int w=edge[i].val;
            if(!w)
            {
                continue;
            }
            if(dis[v]!=0x3f3f3f3f3f3f3f3f)
            {
                continue;
            }
            dis[v]=dis[u]+1;
            q.push(v);
        }
    }
    return dis[T]!=0x3f3f3f3f3f3f3f3f;
}
int dfs(int x,int Cap)
{
    if(x==T)
    {
        return Cap;
    }
    if(!Cap)
    {
        return 0;
    }
    //cerr<<x<<endl;
    int Used=0;
    for(int i=arc[x];i;i=edge[i].nxt)
    {
        arc[x]=i;
        int v=edge[i].to;
        int w=edge[i].val;
        if(!w)
        {
            continue;
        }
        if(dis[v]==dis[x]+1)
        {
            int cap=dfs(v,min(Cap,w));
            edge[i].val-=cap;
            edge[i^1].val+=cap;
            Used+=cap;
            Cap-=cap;
            if(Cap==0)
            {
                break;
            }
        }
    }
    return Used;
}
int dinic()
{
    int Maxflow=0;
    while(bfs())
    {
        int Flow=0;
        while((Flow=dfs(S,INF)))
        {
            //cerr<<"fuc"<<endl;
            Maxflow+=Flow;
        }
    }
    return Maxflow;
}
int n;
int a[105];
int b[105];
bool ck(int x)
{
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            return 0;
        }
    }
    return 1;
}
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%lld",&n);
    vector<pair<int,int> >Odd,Even;
    T=n+1;
    S=0;

    for(int i=1;i<=n;i++)
    {
        scanf("%lld %lld",&a[i],&b[i]);
        if(a[i]&1)
        {
            Odd.push_back(make_pair(a[i],b[i]));
        }
        else
        {
            Even.push_back(make_pair(a[i],b[i]));
        }
    }   

    int Ke=-1;
    for(int i=0;i<Odd.size();i++)
    {
        int v=Odd[i].first;
        
        if(v==1)
        {
            Ke=i;
        }
        else
        {
            add(S,i+1,Odd[i].second);
        }
    }
    for(int i=0;i<Even.size();i++)
    {
        add(i+1+Odd.size(),T,Even[i].second);
    }
    for(int i=0;i<Odd.size();i++)
    {
        for(int j=0;j<Even.size();j++)
        {
            if(ck(Odd[i].first+Even[j].first))
            {
                add(i+1,j+1+Odd.size(),INF);
            }
        }
    }
    int kx=dinic();
    if(Ke!=-1)
    {
        add(S,Ke+1,Odd[Ke].second);
        int Nx=dinic();
        kx+=(edge[cnt_edge-1].val/2)+Nx;
    }
    printf("%lld\n",kx);
}

ABC263Ex

二分明显

对于每条与直线相交得圆,我们处理出该直线的覆盖的角度

可以发现有交即角度区间相交且不包含

这里虽然是环状的,不过我们可以取补集让它不会越过\(0\)

Show Code
#include<bits/stdc++.h>
#define x1 Fgfpf
#define y1 djfngg
#define x2 igdo
#define y2 jdfgdjggg
#define eps 1e-4
using namespace std;
const int MAXN=5e4+5;
const double phi=acos(-1);
int n,k;
struct Slope{
    double A,B,C;
}a[MAXN];
bool G(double a,double b,double c)
{
    return b*b>=4*a*c;
}
pair<double,double>F(double a,double b,double c)
{
    return make_pair((-b+sqrt(b*b-4*a*c))/(2.0*a),(-b-sqrt(b*b-4*a*c))/(2.0*a));
}
double lsh[MAXN*2];
int Bit[MAXN*2];
int lowbit(int x)
{
    return x&(-x);
}
int Cnt=0;
void update(int k,int x)
{
    for(int i=k;i<=Cnt;i+=lowbit(i))
    {
        Bit[i]+=x;
    }
}
int Sum(int k)
{
    int Res=0;
    for(int i=k;i>=1;i-=lowbit(i))
    {
        Res+=Bit[i];
    }
    return Res;
}
vector<int>Rec[MAXN*2];
bool check(double r)
{
    vector<pair<double,double> >V;
    vector<pair<int,int> >U;
    for(int i=1;i<=n;i++)
    {
        if(a[i].B)
        {
            if(G((a[i].A*a[i].A)*1.0/(a[i].B*a[i].B)+1,2.0*a[i].A*a[i].C/(a[i].B*a[i].B),(a[i].C*a[i].C)*1.0/(a[i].B*a[i].B)-r*r))
            {
                auto fkg=F((a[i].A*a[i].A)*1.0/(a[i].B*a[i].B)+1,2.0*a[i].A*a[i].C/(a[i].B*a[i].B),(a[i].C*a[i].C)*1.0/(a[i].B*a[i].B)-r*r);
                double x1=fkg.first;
                double x2=fkg.second;
                double y1,y2;
                if(a[i].B==0)
                {
                    y1=sqrt(r*r-x1*x1);
                    y2=-sqrt(r*r-x1*x1);
                }
                else
                {
                    y1=-(a[i].A*x1/a[i].B+a[i].C/a[i].B);
                    y2=-(a[i].A*x2/a[i].B+a[i].C/a[i].B);
                }
                double L=atan2(x1,y1);
                double R=atan2(x2,y2);
                if(L<0)
                {
                    L+=2*phi;
                }
                if(R<0)
                {
                    R+=2*phi;
                }
                if(L>R)
                {
                    swap(L,R);
                }
                //printf("%lf %lf %lf %lf %lf %lf %d\n",x1,y1,x2,y2,L,R,i);
                V.push_back(make_pair(L,R));
            }
        }
        else
        {
            double x1=-a[i].C*1.0/a[i].A;
            double x2=-a[i].C*1.0/a[i].A;;
            if(x1>=-r&&x1<=r)
            {
                double y1,y2;
                if(a[i].B==0)
                {
                    y1=sqrt(r*r-x1*x1);
                    y2=-sqrt(r*r-x1*x1);
                }
                else
                {
                    y1=-(a[i].A*x1/a[i].B+a[i].C/a[i].B);
                    y2=-(a[i].A*x2/a[i].B+a[i].C/a[i].B);
                }
                double L=atan2(x1,y1);
                double R=atan2(x2,y2);
                if(L<0)
                {
                    L+=2*phi;
                }
                if(R<0)
                {
                    R+=2*phi;
                }
                if(L>R)
                {
                    swap(L,R);
                }
                //printf("%lf %lf %lf %lf %lf %lf %d\n",x1,y1,x2,y2,L,R,i);
                V.push_back(make_pair(L,R));
            }
        }
        
    }
    Cnt=0;
    for(int i=0;i<V.size();i++)
    {
        lsh[++Cnt]=V[i].first;
        lsh[++Cnt]=V[i].second;
    }
    sort(lsh+1,lsh+1+Cnt);
    Cnt=unique(lsh+1,lsh+1+Cnt)-lsh-1;
    for(int i=1;i<=Cnt;i++)
    {
        Bit[i]=0;
        Rec[i].clear();
    }
    for(int i=0;i<V.size();i++)
    {
        U.push_back(make_pair(0,0));
        U[i].first=lower_bound(lsh+1,lsh+1+Cnt,V[i].first)-lsh;
        U[i].second=lower_bound(lsh+1,lsh+1+Cnt,V[i].second)-lsh;
        Rec[U[i].second].push_back(U[i].first);
        //printf("%d %d\n",U[i].first,U[i].second);
    }
    int Tot=0;
    for(int i=1;i<=Cnt;i++)
    {
        for(int j=0;j<Rec[i].size();j++)
        {
            int v=Rec[i][j];
            Tot+=Sum(v);
        }
        for(int j=0;j<Rec[i].size();j++)
        {
            int v=Rec[i][j];
            update(v+1,1);
            update(i+1,-1);
        }
    }
    return Tot>=k;


}
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf %lf %lf",&a[i].A,&a[i].B,&a[i].C);
    }
    //printf("%d\n",check(5));
    //printf("%d?\n",check(2));
    double l=0;
    double r=1e9;
    while(r-l>eps)
    {
        double mid=(l+r)*1.0/2;
        if(check(mid))
        {
            r=mid;
        }
        else
        {
            l=mid;
        }
    }    
    printf("%lf\n",l);
}

ABC262G

zz区间\(dp\)

最开始想偏了,搞出来个\(n^3\)的类似物,结果处理不了值相同的

实际上直接记录\(dp_{l,r,lv,rv}\)表示\([l,r]\)值在\([lv,rv]\)的答案即可

转移直接枚举和\(l\)一起填的数即可

Show Code
#include<bits/stdc++.h>
using namespace std;
int n;
int a[55];
int dp[55][55][55][55];
int dfs(int l,int r,int lv,int rv)
{
    if(dp[l][r][lv][rv]!=-1)
    {
        return dp[l][r][lv][rv];
    }
    if(l>r)
    {
        return 0;
    }
    if(lv>rv)
    {
        return 0;
    }

    if(l==r)
    {
        if(a[l]>=lv&&a[l]<=rv)
        {
            return 1;
        }
        return 0;
    }

    int Res=dfs(l+1,r,lv,rv);
    if(a[l]>=lv&&a[l]<=rv)
    {
        for(int k=l;k<=r;k++)
        {
            Res=max(Res,1+dfs(l+1,k,lv,a[l])+dfs(k+1,r,a[l],rv));
        }
    }   
    dp[l][r][lv][rv]=Res;
    return Res; 
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    memset(dp,-1,sizeof(dp));
    printf("%d\n",dfs(1,n,1,50));
}

ABC262Ex

很典??

不难发现处理出每个点能取到的最大值\(V_i\),单独把\(V_i\)相同的拉出来搞

然后这个问题相当于有若干条限制\([l_i,r_i]\),和若干个点,你可以染色使得每个区间都有染色点

把每个限制放在最后考虑,设\(dp_{i,j}\)表示前\(i\)个点前面第一个被染色的为\(j\)

考虑\(i\)为右端点时的区间左端点最大值为\(h_i\)

\(h_i\le j\le i\)

直接线段树维护一下即可

Show Code
#include<bits/stdc++.h>
#define ls p<<1
#define rs (p<<1)|1
using namespace std;
const int MAXN=4e5+5;
const int MOD=998244353;
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int T;
int n,Q,A;
int l[MAXN],r[MAXN],m[MAXN];
int lshv[MAXN];
int lsh[MAXN];
int fa[MAXN];
int find(int x)
{
    if(fa[x]==x)
    {
        return fa[x];
    }
    fa[x]=find(fa[x]);
    return fa[x];
}
void unionn(int i,int j)
{
    fa[find(i)]=find(j);
}

vector<int>V[MAXN];
vector<int>Rec[MAXN];
int vis[MAXN];
struct Seg{
    int date;
    int l,r;
    int lazy;
}Tree[MAXN*4];
int f[MAXN];
void push_down(int p)
{
    if(Tree[p].lazy)
    {
        Tree[ls].date=0;
        Tree[rs].date=0;
        Tree[ls].lazy=1;
        Tree[rs].lazy=1;

        Tree[p].lazy=0;
    }
}
void push_up(int p)
{
    Tree[p].date=((long long)Tree[ls].date+Tree[rs].date)%MOD;
}
void Build(int p,int l,int r)
{
   // cerr<<"p"<<endl;
    Tree[p].l=l;
    Tree[p].r=r;
    Tree[p].lazy=0;
    if(l==r)
    {
        Tree[p].date=0;
        return;
    }
    int mid=(l+r)>>1;
    Build(ls,l,mid);
    Build(rs,mid+1,r);
    push_up(p);
}
void Update(int p,int l,int r)
{
    //cerr<<"p"<<endl;
    if(l>r)
    {
        return;
    }
    if(Tree[p].l>=l&&Tree[p].r<=r)
    {
        Tree[p].date=0;
        Tree[p].lazy=1;
        return;
    }
    push_down(p);
    int mid=(Tree[p].l+Tree[p].r)>>1;
    if(l<=mid)
    {
        Update(ls,l,r);
    }
    if(r>mid)
    {
        Update(rs,l,r);
    }
    push_up(p);
}
void Insert(int p,int k,int x)
{
    //cerr<<"p"<<endl;
    if(Tree[p].l==Tree[p].r)
    {
        Tree[p].date=x;
        return;
    }
    push_down(p);
    int mid=(Tree[p].l+Tree[p].r)>>1;
    if(k<=mid)
    {
        Insert(ls,k,x);
    }
    else
    {
        Insert(rs,k,x);
    }
    push_up(p);
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    T=1;
    while(T--)
    {
        scanf("%d %d %d",&n,&A,&Q);
        A++;
        int cntv=0,cnt=0;
        for(int i=1;i<=Q;i++)
        {
            scanf("%d %d %d",&l[i],&r[i],&m[i]);
            m[i]++;
            lshv[++cntv]=m[i];
            lsh[++cnt]=l[i];
            lsh[++cnt]=r[i]+1;
        }
        sort(lshv+1,lshv+1+cntv);
        cntv=unique(lshv+1,lshv+1+cntv)-lshv-1;
        for(int i=1;i<=cntv;i++)
        {
            V[i].clear();
        }
        lsh[++cnt]=1;
        lsh[++cnt]=n+1;
        sort(lsh+1,lsh+1+cnt);
        cnt=unique(lsh+1,lsh+1+cnt)-lsh-1;
        
        for(int i=1;i<=Q;i++)
        {
            l[i]=lower_bound(lsh+1,lsh+1+cnt,l[i])-lsh;
            r[i]=lower_bound(lsh+1,lsh+1+cnt,r[i]+1)-lsh-1;

            m[i]=lower_bound(lshv+1,lshv+1+cntv,m[i])-lshv;
            V[m[i]].push_back(i);
        }       

        for(int i=1;i<=cnt+1;i++)
        {
            fa[i]=i;
            vis[i]=0;
        }
        int Res=1;
        for(int i=1;i<=cntv;i++)
        {
            vector<int>Used;
            //cerr<<i<<endl;
            for(int j=0;j<V[i].size();j++)
            {
                int id=V[i][j];
                int Now=find(l[id]);
                //printf("%d %d\n",l[id],r[id]);
                while(Now<=r[id])
                {
                    if(!vis[Now])
                    {
                        vis[Now]=1;
                        Used.push_back(Now);
                    }
                    int to=find(Now+1);
                    //cerr<<"fu"<<endl;
                    unionn(Now,to);
                    Now=to;
                    

                }
                

            }
            
            sort(Used.begin(),Used.end());
            for(int j=0;j<Used.size();j++)
            {
                Rec[j].clear();
            }
            for(int j=0;j<V[i].size();j++)
            {
                int id=V[i][j];
                int L=lower_bound(Used.begin(),Used.end(),l[id])-Used.begin();
                int R=upper_bound(Used.begin(),Used.end(),r[id])-Used.begin()-1;
                if(L>R)
                {
                    Res=0;
                    break;
                }

                Rec[R].push_back(L);
                //printf("%d %d\n",L,R);
            }

            f[0]=1;
            Build(1,0,Used.size());
            Insert(1,0,1);
            int Mul=1;
            for(int j=1;j<=Used.size();j++)
            {
                if(lshv[i]>1)
                {
                    int v=lsh[Used[j-1]+1]-lsh[Used[j-1]];
                    Mul=((long long)Mul*Pow(lshv[i]-1,v,MOD)%MOD);
                    int H=0;
                    for(int k=0;k<Rec[j-1].size();k++)
                    {
                        int p=Rec[j-1][k];
                        H=max(H,p+1);
                    }
                    Update(1,0,H-1);
                    int xks=((long long)f[j-1]*(((long long)Pow(lshv[i],v,MOD)-Pow(lshv[i]-1,v,MOD)+MOD)%MOD))%MOD;
                    xks=((long long)xks*inv(Mul,MOD))%MOD;
                    Insert(1,j,xks);
                    f[j]=((long long)Tree[1].date*Mul)%MOD;
                }
                else
                {
                    f[j]=1;
                }
                
            }
            //printf("%d %d??\n",f[Used.size()],Used.size());
            Res=((long long)Res*f[Used.size()])%MOD;
        }
        int tot=0;
        for(int i=1;i<cnt;i++)
        {
            if(find(i)==i)
            {
                tot+=lsh[i+1]-lsh[i];
            }
        }        
        Res=((long long)Res*Pow(A,tot,MOD))%MOD;
        printf("%d\n",Res);
    }
}

ABC261G

有趣的半屉?

首先有一个不大成熟的思路是我们考虑求出\(f_{c,l,r}\)为用字符\(c\)得到\([l,r]\)的最小代价

这个\(f_{c,l,r}\)我们考虑把它分为若干个段求解,如果直接枚举每条边求解里面跑\(dp\)复杂度大概是\(26\times 50^5\)

这里再设\(g_{l,r,k,i}\)表示用第\(k\)个关系的前\(i\)个字符能得到\([l,r]\)的最小代价

这样似乎就可以转移了

有个问题,单个字符之间的转移时有问题的,因为没有后效性

因此我们在单个字符之间要跑一次\(floyd\)

Show Code
#include<bits/stdc++.h>
using namespace std;
int n;
string s;
string t,tmp;
int dis[27][27];
vector<int>G[27];
string v[55];
int f[27][55][55];
int g[55][55][55][55];
int dp[55][55];
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    cin>>s;
    cin>>t;
    scanf("%d",&n);
    memset(dis,0x3f,sizeof(dis));
    for(int i=1;i<=n;i++)
    {
        cin>>tmp;
        cin>>v[i];
        G[tmp[0]-'a'+1].push_back(i);
        if(v[i].size()==1)
        {
            dis[v[i][0]-'a'+1][tmp[0]-'a'+1]=1;
        }
    }
    for(int k=1;k<=26;k++)
    {
        for(int i=1;i<=26;i++)
        {
            for(int j=1;j<=26;j++)
            {
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
    int m=t.size();
    memset(f,0x3f,sizeof(f));
    memset(g,0x3f,sizeof(g));
    for(int j=0;j<m;j++)       
    {
        f[t[j]-'a'+1][j][j]=0;
    }
   
    for(int p=0;p<m;p++)
    {
        for(int k=1;k<=26;k++)
        {
            for(int i=1;i<=26;i++)
            {
                for(int j=1;j<=26;j++)
                {
                    f[i][p][p]=min(f[i][p][p],f[j][p][p]+dis[j][i]);
                }
            }
        }
    }

    for(int j=0;j<m;j++)
    {
        for(int i=1;i<=n;i++)
        {
            
            g[j][j][i][0]=f[v[i][0]-'a'+1][j][j];
        }
    }
    //printf("%d %d")
     //printf("%d %d %d %d %d %d::\n",f[2][1][1],t[2]-'a'+1,g[0][0][2][0],f[1][1][1],dis[2][1]);
    for(int len=2;len<=m;len++)
    {
        for(int l=0;l+len-1<m;l++)
        {
            int r=l+len-1;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<v[i].size();j++)
                {
                    for(int k=l;k<r;k++)
                    {
                        g[l][r][i][j]=min(g[l][r][i][j],g[l][k][i][j-1]+f[v[i][j]-'a'+1][k+1][r]);
                    }
                }
            }
            //printf("%d %d %d---------\n",f[2][1][1],t[2]-'a'+1,g[0][1][2][1]);
            for(int i=1;i<=26;i++)
            {
                for(int j=0;j<G[i].size();j++)
                {
                    int vw=G[i][j];
                    f[i][l][r]=min(f[i][l][r],g[l][r][vw][v[vw].size()-1]+1);
                }
            }

            // for(int k=1;k<=26;k++)
            // {
            //     for(int i=1;i<=26;i++)
            //     {
            //         for(int j=1;j<=26;j++)
            //         {
            //             f[i][l][r]=min(f[i][l][r],f[j][l][r]+dis[j][i]);
            //         }
            //     }
            // }
            // for(int i=1;i<=n;i++)
            // {
            //     g[l][r][i][0]=f[v[i][0]-'a'+1][l][r];
            // }//只有一个可以互相转移
            // for(int i=1;i<=26;i++)
            // {
            //     if(f[i][l][r]!=0x3f3f3f3f)
            //     {
            //         printf("%d %d %d %d::\n",i,l,r,f[i][l][r]);
            //     }
                
            // }
        }
    }
   // printf("%d %d %d %d %d??\n",g[0][0][20][0],f['n'-'a'+1][0][0],f['n'-'a'+1][0][1],f['n'-'a'+1][1][1],g[0][1][20][1]);
    //printf("%d::\n",f[1][1][1]);
    memset(dp,0x3f,sizeof(dp));
    dp[0][0]=0;
    for(int i=1;i<=t.size();i++)
    {
        for(int j=1;j<=s.size();j++)
        {
            for(int k=0;k<i;k++)
            {
                dp[i][j]=min(dp[i][j],dp[k][j-1]+f[s[j-1]-'a'+1][k][i-1]);
            }
        }
    }
    
    if(dp[t.size()][s.size()]==0x3f3f3f3f)
    {
        printf("-1\n");
    }
    else
    {
        printf("%d\n",dp[t.size()][s.size()]);
    }
}

ABC261Ex

脑袋被僵尸吃了/kk

和省选那题极度相似

解释一下为啥最大值是这样

因为对于\(1\),当前更新出度为\(0\)的它是一个都不想走,只想走到环上

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
int n,m;
int x,y,z;
struct Edge{
    int v,val;
};
vector<Edge>g[MAXN];
long long dp[MAXN][2];
int vis[MAXN][2];
int rd[MAXN];
int k;
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&x,&y,&z);
        g[y].push_back((Edge){x,z});
        rd[x]++;
    }
    priority_queue<pair<long long,pair<int,int> > >Q;
    for(int i=1;i<=n;i++)
    {
        dp[i][0]=2e18;
        dp[i][1]=0;
    }
    for(int i=1;i<=n;i++)
    {
        if(!rd[i])
        {
            Q.push(make_pair(0,make_pair(i,0)));
            Q.push(make_pair(0,make_pair(i,1)));
            dp[i][0]=dp[i][1]=0;
        }
    }
    while(Q.size())
    {
        auto it=Q.top().second;
        Q.pop();
        if(vis[it.first][it.second])
        {
            continue;
        }
        
        vis[it.first][it.second]=1;
        for(int i=0;i<g[it.first].size();i++)
        {
            int v=g[it.first][i].v;
            int w=g[it.first][i].val;
            if(it.second==0)
            {
                dp[v][1]=max(dp[v][1],dp[it.first][0]+w);
                rd[v]--;
                if(!rd[v])
                {
                    Q.push(make_pair(-dp[v][1],make_pair(v,1)));
                }
            }
            else
            {
                dp[v][0]=min(dp[v][0],dp[it.first][1]+w);
                Q.push(make_pair(-dp[v][0],make_pair(v,0)));
            }
        }
    }

    if(vis[k][0])
    {
        printf("%lld\n",dp[k][0]);
    }
    else
    {
        printf("INFINITY");
    }
    

}

ABC260G

nt差分,调了一下午自闭了

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=9005;
int n,m,q;
int x,y;
char mp[MAXN][MAXN];
int cf1[MAXN][MAXN];
int cf2[MAXN][MAXN];
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",mp[i]+1);
    }
    m=2*m-1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(mp[i][j]=='O')
            {
                int x=2*i-1;
                int y=j;
                cf1[x][y]++;
                if(y+m+1<=MAXN-5)
                {
                    cf1[x][y+m+1]--;
                    cf2[x][y+m+1]++;
                }
                
                if(x+m+1<=MAXN-5)
                {
                    cf2[x+m+1][y]--;
                }
                
                
            }       
        }
    }
    //     for(int i=1;i<=5;i++)
    // {
    //     for(int j=1;j<=5;j++)
    //     {
    //         printf("%5d",cf2[i][j]);
    //     }
    //     printf("\n");
    // }

    // printf("\n");
    for(int i=MAXN-5;i>=1;i--)
    {
        for(int j=1;j<=MAXN-5;j++)
        {
            cf2[i][j]+=cf2[i+1][j-1];
        }
    }
    // for(int i=1;i<=5;i++)
    // {
    //     for(int j=1;j<=5;j++)
    //     {
    //         printf("%5d",cf2[i][j]);
    //     }
    //     printf("\n");
    // }

    // printf("\n");
    for(int i=1;i<=MAXN-5;i++)
    {
        for(int j=1;j<=MAXN-5;j++)
        {
            cf1[i][j]=cf1[i][j]+cf1[i][j-1];
        }
    }
    for(int i=1;i<=MAXN-5;i++)
    {
        for(int j=1;j<=MAXN-5;j++)
        {
            cf1[i][j]=cf1[i][j]+cf2[i][j];
        }
    }
    
    // for(int i=1;i<=5;i++)
    // {
    //     for(int j=1;j<=5;j++)
    //     {
    //         printf("%5d",cf1[i][j]);
    //     }
    //     printf("\n");
    // }
    for(int i=1;i<=MAXN-5;i++)
    {
        for(int j=1;j<=MAXN-5;j++)
        {
            cf1[i][j]=cf1[i][j]+cf1[i-1][j];
        }
    }
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d %d",&x,&y);
        printf("%d\n",cf1[2*x-1][y]);
    }

}

ABC259G

和文理分科差不多的玩意,好像吧

Show Code
#include<bits/stdc++.h>
#define int long long
#define INF 2e18
using namespace std;
const int MAXN=405;
struct Edge{
    int to,val,nxt;
}edge[MAXN*MAXN*10];
int cnt_edge=1;
int head[MAXN*10];
void Add(int u,int v,int val)
{
    edge[++cnt_edge].val=val;
    edge[cnt_edge].nxt=head[u];
    edge[cnt_edge].to=v;
    head[u]=cnt_edge;
}
void add(int u,int v,int val)
{
    Add(u,v,val);
    Add(v,u,0);
}
int S,T;
int dis[MAXN*10];
int arc[MAXN*10];
int bfs()
{
    queue<int>q;
    q.push(S);
    for(int i=S;i<=T;i++)
    {
        dis[i]=-1;
    }
    dis[S]=0;
    while(q.size())
    {
        int u=q.front();
        q.pop();
        arc[u]=head[u];
        for(int i=head[u];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            int w=edge[i].val;
            if(!w)
            {
                continue;
            }
            if(dis[v]!=-1)
            {
                continue;
            }
            dis[v]=dis[u]+1;
            q.push(v);
        }
    }
    return dis[T]!=-1;
}
int dfs(int x,int Cap)
{
    if(x==T)
    {
        return Cap;
    }
    if(Cap==0)
    {
        return Cap;
    }
    //cerr<<x<<endl;
    int Used=0;
    for(int i=arc[x];i;i=edge[i].nxt)
    {
        arc[x]=i;
        int v=edge[i].to;
        int w=edge[i].val;
        if(dis[v]==dis[x]+1)
        {
            if(!w)
            {
                continue;
            }
            int cap=dfs(v,min(w,Cap));
            Cap-=cap;
            Used+=cap;
            edge[i].val-=cap;
            edge[i^1].val+=cap;
            if(Cap==0)
            {
                break;
            }
        }
    }
    return Used;
}
int dinic()
{
    int Maxflow=0;
    while(bfs())
    {
        int Flow;
        while((Flow=dfs(S,INF)))
        {
            Maxflow+=Flow;
        }
    }
    return Maxflow;
}
int n,m;
int a[MAXN][MAXN];
signed main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%lld %lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%lld",&a[i][j]);
        }
    }
    S=0;
    T=n+m+1;
    long long Res=0;
    for(int i=1;i<=n;i++)
    {
        long long Sum=0;
        for(int j=1;j<=m;j++)
        {
            Sum+=a[i][j];
        }
        if(Sum>0)
        {
            add(S,i,Sum);
            Res+=Sum;
        }
        
    }
    for(int i=1;i<=m;i++)
    {
        long long Sum=0;
        for(int j=1;j<=n;j++)
        {
            Sum+=a[j][i];
        }
        if(Sum>0)
        {
            add(i+n,T,Sum);
            Res+=Sum;
        }
        
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]>=0)
            {
                add(i,j+n,a[i][j]);
            }
            else
            {
                add(i,j+n,INF);
            }
            
        }
    }
    // printf("%lld\n",Res);
    // for(int i=S;i<=T;i++)
    // {
    //     for(int j=head[i];j;j=edge[j].nxt)
    //     {
    //         if(edge[j].val)
    //         {
    //             printf("%d %d %d\n",i,edge[j].to,edge[j].val);
    //         }
            
    //     }
    // }
    printf("%lld\n",Res-dinic());
}

ABC258Ex

zz矩乘,一直往容斥的方向想,真小丑

Show Code
// LUOGU_RID: 135388999
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
const int MOD=998244353;
long long S;
int n;
long long a[MAXN];
struct Martix{
    int val[3][3];
    void clear()
    {
        memset(val,0,sizeof(val));
    }
    void init()
    {
        clear();
        for(int i=0;i<=2;i++)
        {
            val[i][i]=1;
        }
    }
    Martix operator*(const Martix x)const{
        Martix Res;
        Res.clear();
        for(int k=0;k<=2;k++)
        {
            for(int i=0;i<=2;i++)
            {
                for(int j=0;j<=2;j++)
                {
                    Res.val[i][j]=((long long)Res.val[i][j]+((long long)val[i][k]*x.val[k][j])%MOD)%MOD;
                }
            }
        }
        return Res;
    }
}A,B;
Martix Pow(Martix a,long long b)
{
    Martix res;
    res.init();
    while(b)
    {
        if(b&1)
        {
            res=res*a;
        }
        a=a*a;
        b>>=1;
    }
    return res;
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %lld",&n,&S);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }   
    Martix Res;
    Res.clear();
    Res.val[0][0]=1;
    Res.val[0][1]=1;
    Res.val[0][2]=0;

    A.val[0][0]=0;A.val[0][1]=0;A.val[0][2]=0;
    A.val[1][0]=1;A.val[1][1]=1;A.val[1][2]=1;
    A.val[2][0]=0;A.val[2][1]=1;A.val[2][2]=0;

    B.val[0][0]=0;B.val[0][1]=0;B.val[0][2]=0;
    B.val[1][0]=0;B.val[1][1]=0;B.val[1][2]=1;
    B.val[2][0]=0;B.val[2][1]=1;B.val[2][2]=0;
    for(int i=1;i<=n;i++)
    {
        long long d=a[i]-a[i-1]-1;
        Res=Res*Pow(A,d);
        Res=Res*B;
    }
    Res=Res*Pow(A,S-a[n]);
    printf("%d",Res.val[0][0]);
}

ABC256G

zz矩乘

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int MAXN=1e4+5;
int D;
long long n;
struct Martix{
    int val[2][2];
    void clear()
    {
        memset(val,0,sizeof(val));
    }
    void init()
    {
        clear();
        for(int i=0;i<=1;i++)
        {
            val[i][i]=1;
        }
    }
    Martix operator*(const Martix x)const{
        Martix Res;
        Res.clear();
        for(int k=0;k<=1;k++)
        {
            for(int i=0;i<=1;i++)
            {
                for(int j=0;j<=1;j++)
                {
                    Res.val[i][j]=((long long)Res.val[i][j]+((long long)val[i][k]*x.val[k][j])%MOD)%MOD;
                }
            }
        }
        return Res;
    }
}A;
int Pow(int a,int b,int p)
{
    int res=1;
    int base=a;
    while(b)
    {
        if(b&1)
        {
            res=((long long)res*base)%p;
        }
        base=((long long)base*base)%p;
        b>>=1;
    }
    return res;
}
int inv(int a,int p)
{
    return Pow(a,p-2,p);
}
int fac[MAXN];
int inv_fac[MAXN];
int C(int n,int m)
{
    if(n<m||m<0)
    {
        return 0;
    }
    if(n==m||m==0)
    {
        return 1;
    }
    //printf("%d %d %d:::\n",n,m,((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD);
    return ((((long long)fac[n]*inv_fac[m])%MOD)*inv_fac[n-m])%MOD;
}
Martix Pw(Martix a,long long b)
{
    Martix res;
    res.init();
    while(b)
    {
        if(b&1)
        {
            res=res*a;
        }
        a=a*a;
        b>>=1;
    }
    return res;
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    fac[0]=1;
    for(int i=1;i<=MAXN-5;i++)
    {
        fac[i]=((long long)fac[i-1]*i)%MOD;
    }
    inv_fac[MAXN-5]=inv(fac[MAXN-5],MOD);
    for(int i=MAXN-5-1;i>=1;i--)
    {
        inv_fac[i]=((long long)inv_fac[i+1]*(i+1))%MOD;
    }
    scanf("%lld %d",&n,&D);
    int Res=0;
    D++;
    for(int i=0;i<=D;i++)
    {
        A.val[0][0]=C(D-2,i);A.val[0][1]=C(D-2,i-1);
        A.val[1][0]=C(D-2,i-1);A.val[1][1]=C(D-2,i-2);
        A=Pw(A,n);
        Res=((long long)Res+A.val[0][0])%MOD;
        Res=((long long)Res+A.val[1][1])%MOD;
      //  printf("%d %d %d??\n",i,A.val[0][0],A.val[1][1]);
    }
    printf("%d\n",Res);
}

ABC255G

求SG,手完一下,直接处理特殊点,其他点依次平移

特殊点删除有点麻烦,注意到我们可以直接处理出需要用到\(sg\)的个数即可

Show Code
// LUOGU_RID: 135443779
#include<bits/stdc++.h>
using namespace std;
const int MAXN=6e5+5;
int n,m;
long long a[MAXN];
map<long long,int>Vis;
long long x,y;
vector<long long>g[MAXN];
long long Sg[MAXN];
map<long long,int>Num;
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%d %d",&n,&m);
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        if(!Vis[a[i]])
        {
            Vis[a[i]]=++cnt;
        }
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%lld %lld",&x,&y);
        if(!Vis[x])
        {
            Vis[x]=++cnt;
        }
        if(!Vis[x-y])
        {
            Vis[x-y]=++cnt;
        }

        g[Vis[x]].push_back(Vis[x-y]);
    }
    int del=0;
    for(auto it=Vis.begin();it!=Vis.end();it++)
    {
        auto tmp=(*it);

        Sg[tmp.second]=tmp.first-del;
        for(int j=0;j<g[tmp.second].size();j++)
        {
            int v=g[tmp.second][j];
            Num[Sg[v]]--;
            if(!Num[Sg[v]])
            {
                Sg[tmp.second]=min(Sg[tmp.second],Sg[v]);
            }
        }

        for(int j=0;j<g[tmp.second].size();j++)
        {
            int v=g[tmp.second][j];
            Num[Sg[v]]++;
        }

        Num[Sg[tmp.second]]++;
        if(Sg[tmp.second]!=tmp.first-del)
        {
            del++;
        }
   //     printf("%lld %lld\n",tmp.first,Sg[tmp.second]);
    }
    long long sx=0;
    for(int i=1;i<=n;i++)
    {
        sx^=Sg[Vis[a[i]]];
    }
    if(sx)
    {
        printf("Takahashi");
    }
    else
    {
        printf("Aoki");
    }
}

ABC255Ex

线段树半屉

Show Code
// LUOGU_RID: 135457847
#include<bits/stdc++.h>
#define ls p<<1
#define rs (p<<1)|1
using namespace std;
const int MOD=998244353;
const int MAXN=4e5+5;
const int inv2=MOD-MOD/2;
int Q;
long long n;
struct Qry{
    long long D,l,r; 
}qur[MAXN];
long long D,l,r;
long long lsh[MAXN];
struct Seg{
    int lazy1;
    int lazy2;
    int l,r;
    int sd;
}Tree[MAXN*4];
void push_down(int p)
{
    if(Tree[p].lazy1)
    {
        Tree[ls].lazy1=1;
        Tree[ls].sd=0;
        Tree[ls].lazy2=0;

        Tree[rs].lazy1=1;
        Tree[rs].sd=0;
        Tree[rs].lazy2=0;

        Tree[p].lazy1=0;
    }

    if(Tree[p].lazy2)
    {
        Tree[ls].lazy2=((long long)Tree[ls].lazy2+Tree[p].lazy2)%MOD;
        int Amx=(lsh[Tree[ls].r+1]-1+lsh[Tree[ls].l])%MOD;
        Amx=((long long)Amx*(((lsh[Tree[ls].r+1]-lsh[Tree[ls].l]))%MOD))%MOD;
        Amx=((long long)Amx*inv2)%MOD;
        Amx=((long long)Amx*Tree[p].lazy2)%MOD;
        Tree[ls].sd=((long long)Tree[ls].sd+Amx)%MOD;

        Tree[rs].lazy2=((long long)Tree[rs].lazy2+Tree[p].lazy2)%MOD;
        Amx=(lsh[Tree[rs].r+1]-1+lsh[Tree[rs].l])%MOD;
        Amx=((long long)Amx*(((lsh[Tree[rs].r+1]-lsh[Tree[rs].l]))%MOD))%MOD;
        Amx=((long long)Amx*inv2)%MOD;
        Amx=((long long)Amx*Tree[p].lazy2)%MOD;
        Tree[rs].sd=((long long)Tree[rs].sd+Amx)%MOD;

        Tree[p].lazy2=0;
    }
}
void push_up(int p)
{
    Tree[p].sd=((long long)Tree[ls].sd+Tree[rs].sd)%MOD;
}
void Build(int p,int l,int r)
{
    Tree[p].l=l;
    Tree[p].r=r;
    Tree[p].lazy1=0;
    Tree[p].lazy2=0;
    if(l==r)
    {
        Tree[p].sd=0;
        return;
    }
    int mid=(l+r)>>1;
    Build(ls,l,mid);
    Build(rs,mid+1,r);
    push_down(p);
}
void Update1(int p,int l,int r)
{
    if(Tree[p].l>=l&&Tree[p].r<=r){
        Tree[p].sd=0;
        Tree[p].lazy1=1;
        Tree[p].lazy2=0;
        return;
    }
    int mid=(Tree[p].l+Tree[p].r)>>1;
    push_down(p);
    if(l<=mid)
    {
        Update1(ls,l,r);
    }
    if(r>mid)
    {
        Update1(rs,l,r);
    }
    push_up(p);
}
void Update2(int p,int l,int r,int x)
{
    if(Tree[p].l>=l&&Tree[p].r<=r)
    {
        int Amx;
        Tree[p].lazy2=((long long)Tree[p].lazy2+x)%MOD;
        Amx=(lsh[Tree[p].r+1]-1+lsh[Tree[p].l])%MOD;
        Amx=((long long)Amx*(((lsh[Tree[p].r+1]-lsh[Tree[p].l]))%MOD))%MOD;
        Amx=((long long)Amx*inv2)%MOD;
        Amx=((long long)Amx*x)%MOD;
        Tree[p].sd=((long long)Tree[p].sd+Amx)%MOD;
        //printf("%d %d %d::\n",Tree[p].l,Tree[p].r,Tree[p].sd);
        return;
    }
    push_down(p);
    int mid=(Tree[p].l+Tree[p].r)>>1;
    if(l<=mid)
    {
        Update2(ls,l,r,x);
    }
    if(r>mid)
    {
        Update2(rs,l,r,x);
    }
    push_up(p);
}
int Query(int p,int l,int r)
{
    if(Tree[p].l>=l&&Tree[p].r<=r)
    {
        return Tree[p].sd;
    }
    int mid=(Tree[p].l+Tree[p].r)>>1;
    push_down(p);
    // printf("%d %d %d::\n",Tree[ls].l,Tree[ls].r,Tree[ls].sd);
    // printf("%d %d %d::\n",Tree[rs].l,Tree[rs].r,Tree[rs].sd);
    int Res=0;
    if(l<=mid)
    {
        Res=((long long)Res+Query(ls,l,r))%MOD;
    }
    if(r>mid)
    {
        Res=((long long)Res+Query(rs,l,r))%MOD;
    }
    return Res;
}
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    scanf("%lld",&n);
    scanf("%d",&Q);
    int Cnt=0;
    for(int i=1;i<=Q;i++)
    {
        scanf("%lld %lld %lld",&D,&l,&r);
        qur[i]=(Qry{D,l,r});
        lsh[++Cnt]=l;
        lsh[++Cnt]=r+1;
    }
    sort(lsh+1,lsh+1+Cnt);
    Cnt=unique(lsh+1,lsh+1+Cnt)-lsh-1;
    Build(1,1,Cnt-1);
    long long L=0;
    for(int i=1;i<=Q;i++)
    {
        D=qur[i].D;
        l=qur[i].l;
        r=qur[i].r;
        l=lower_bound(lsh+1,lsh+1+Cnt,l)-lsh;
        r=lower_bound(lsh+1,lsh+1+Cnt,r+1)-lsh-1;
        Update2(1,1,Cnt-1,(D-L)%MOD);
        //printf("%d %d::\n",l,r);
        int S=Query(1,l,r);
        Update1(1,l,r);
        printf("%d\n",S);
        L=D;

    }

}

[ABC280Ex] Substring Sort

codechef春春贵物,还得看AT

后缀树半屉

Show Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+6;
void read(long long &x)
{
    x=0;
    int f=1;
    char s=getchar();
    while(s<'0'||s>'9')
    {
        s=getchar();
    }
    while(s>='0'&&s<='9')
    {
        x=x*10+(s-'0');
        s=getchar();
    }
    return;
}
int n;
string S[MAXN];
struct SAM{
    int len,link;
    int num;
    int nxt[26];
    pair<int,int> col;
}Tree[MAXN*2];
int cnt_node;
void Build()
{
    Tree[0].link=-1;
    return;
}  
int las;
int Insert(char s,int Pos,int id)
{
    int cur=++cnt_node;
    int p=las;
    Tree[cur].len=Tree[p].len+1;
    while((p!=-1)&&(!Tree[p].nxt[s-'a']))
    {
        //printf("%d %d??\n",p);
        Tree[p].nxt[s-'a']=cur;
        p=Tree[p].link;
    }
    //printf("%d %d %d??\n",Tree[1].nxt[0],las,Tree[1].link);
    if(p==-1)
    {
        Tree[cur].link=0;
    }
    else
    {
        int q=Tree[p].nxt[s-'a'];
        if(Tree[q].len!=Tree[p].len+1)
        {

            int clone=++cnt_node;
            Tree[clone].link=Tree[q].link;
            Tree[clone].len=Tree[p].len+1;
            for(int i=0;i<26;i++)
            {
                Tree[clone].nxt[i]=Tree[q].nxt[i];
            }
            Tree[cur].link=clone;
            Tree[q].link=clone;
            
            while((p!=-1)&&(Tree[p].nxt[s-'a']==q))
            {   
                Tree[p].nxt[s-'a']=clone;
                p=Tree[p].link;
            }

        }
        else
        {
            Tree[cur].link=q;
        }
    }
    Tree[cur].col=make_pair(id,Pos);
    Tree[cur].num=1;
    //printf("%d %d??\n",Pos,cur);
    return cur;
}
vector<int>g[MAXN*2];
void dfs1(int x)
{
    for(int i=0;i<g[x].size();i++)
    {
        int v=g[x][i];
        dfs1(v);
        Tree[x].col=Tree[v].col;
    }
}
int cmp(int x,int y)
{
    return S[Tree[x].col.first][Tree[x].col.second+Tree[Tree[x].link].len-1]<S[Tree[y].col.first][Tree[y].col.second+Tree[Tree[y].link].len-1];
}
int cnt_dfn;
int dfn[MAXN*2];
int Rlf[MAXN*2];
int dp[MAXN*2][22];
void dfs2(int x)
{
    sort(g[x].begin(),g[x].end(),cmp);
    Rlf[++cnt_dfn]=x;
    dfn[x]=cnt_dfn;
    if(x)
    {
        dp[x][0]=Tree[x].link;
        for(int j=1;j<=20;j++)
        {
            dp[x][j]=dp[dp[x][j-1]][j-1];
        }
    }
    for(int i=0;i<g[x].size();i++)
    {
        int v=g[x][i];
        dfs2(v);
        Tree[x].num+=Tree[v].num;
    }
}
int q;
long long Q[MAXN];
int main()
{
    // freopen("date.in","r",stdin);
    // freopen("date.out","w",stdout);
    Build();
    scanf("%d",&n);
    for(int j=1;j<=n;j++)
    {
        las=0;
         cin>>S[j];
        reverse(S[j].begin(),S[j].end());
        for(int i=0;i<S[j].size();i++)
        {
            las=Insert(S[j][i],(int)S[j].size()-i,j);
        }
        reverse(S[j].begin(),S[j].end());
    }
   
    for(int i=1;i<=cnt_node;i++)
    {
        //printf("%d %d\n",Tree[i].link,i);
        g[Tree[i].link].push_back(i);
    }
    dfs1(0);
    dfs2(0);
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%lld",&Q[i]);
    }
    long long Noi=0;
    int Pi=1;
    for(int i=1;i<=cnt_dfn;i++)
    {
        if(!Rlf[i])
        {
            continue;
        }
        int x=Rlf[i];
        int Len=(Tree[x].len-Tree[Tree[x].link].len);
        while(Pi<=q&&(Q[Pi]<=Noi+((long long)Len*Tree[x].num)))
        {
            long long Res=Q[Pi]-Noi;
        
            Res=((Res-1)/(Tree[x].num))+1;
            
            int Lx=Tree[Tree[x].link].len+Res;
            printf("%d %d %d\n",Tree[x].col.first,Tree[x].col.second,Tree[x].col.second+Lx-1);
            ++Pi;
        }
        Noi+=((long long)Len*Tree[x].num);
    }
    // printf("%lld %d",Noi,Q[q]);
}

posted @ 2023-09-28 22:22  kid_magic  阅读(37)  评论(6编辑  收藏  举报