WY模拟赛7

WY模拟赛7

T1. 洛谷 P12674 「LAOI-8」Count

原题

前缀积+非常巧妙的桶优化。

code:

#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef longlong ll; 
const int N=3e5+5,M=1e6+520,mod=998244353;
const int inf=INT_MAX,INF=1e9+7; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
fuck int ksm(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}
fuck int inv(int x){return ksm(x,mod-2);} 
int n,a[N],dp[N],sum[N],f[N];
int sumd[45],sumf[45],sumi[45];
fuck void solve()
{
    cin>>n;
    memset(sumd,0,sizeof(sumd));
    memset(sumf,0,sizeof(sumf));
    memset(sumi,0,sizeof(sumi));
    for(int i=0;i<n;i++)cin>>a[i];
    dp[0]=0;f[0]=1;sum[0]=1;
    sumd[a[0]]=(sumd[a[0]]+dp[0])%mod;
    sumf[a[0]]=(sumf[a[0]]+f[0])%mod;
    sumi[a[0]]=(sumi[a[0]]+f[0]*inv(sum[0])%mod)%mod;
    for(int i=1;i<=n;i++)
    {
        sum[i]=sum[i-1]*a[i-1]%mod;
        dp[i]=(sumd[a[i-1]]+sum[i]*sumi[a[i-1]]%mod)%mod;
        f[i]=sumf[a[i-1]];
        // cout<<sum[i]<<" "<<dp[i]<<" "<<f[i]<<"\n";
        if(i<n)
        {
            int nt=a[i];
            sumd[nt]=(sumd[nt]+dp[i])%mod;
            sumf[nt]=(sumf[nt]+f[i])%mod;
            sumi[nt]=(sumi[nt]+f[i]*inv(sum[i])%mod)%mod;
        }
    }
    cout<<(dp[n]+mod)%mod<<"\n";
}
signed main() 
{ 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int fuckccf=read();
    // for(int i=1;i<=tot;i++)cout<<prime[i]<<"\n";
    // int QwQ=read();
    // while(QwQ--)solve(); 
    solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666



T2. 洛谷 P10793 『SpOI - R1』Double Champions

原题

首先处理掉包含了别人的劣区段,然后处理完后按左端点由小到大排序后可以发现区间的右端点,嘿,它是单调不减的,于是单调队列优化一下。

#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=3e5+5,M=64,mod=998244353;
const int inf=INT_MAX,INF=1e9+7; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n,w;
struct node
{
    int l,r,id;
}pp[N];
int vis[N],f[N];
fuck bool cmp1(node a,node b){return a.l==b.l?a.r<b.r:a.l>b.l;}
fuck bool cmp2(node a,node b){return a.l==b.l?a.r<b.r:a.l<b.l;}
vector<node>g;
fuck void solve()
{
    n=read(),w=read();g.clear();
    int ff=0;
    for(int i=1;i<=n;i++)
    {
        pp[i].l=read(),pp[i].r=read();
        if(pp[i].r-pp[i].l+1<w)ff=1;
    }
    if(ff==1){cout<<"No"<<endl;return;}
    sort(pp+1,pp+n+1,cmp1);
    int mr=inf;
    for(int i=1;i<=n;i++)
    {
        if(pp[i].r>=mr)continue;
        else if(pp[i].r<mr)mr=pp[i].r;
        g.push_back(pp[i]);
    }
    sort(g.begin(),g.end(),cmp2);
    queue<int>q;f[0]=0;
    for(int i=1;i<=g.size();i++)
    {
        q.push(i);
        while(max(0*1ll,g[q.front()-1].r-g[i-1].l+1)<w)q.pop();
        f[i]=f[q.front()-1]+1;
    }
    // while(q.size())q.pop();
    cout<<f[g.size()]<<"\n";
}
signed main() 
{ 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int fuckccf=read();
    int QwQ=read();
    while(QwQ--)solve(); 
    // solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666



T3. 洛谷 P9400 「DBOI」Round 1 三班不一般

原题

线段树优化dp,难写。

#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=2e5+5,M=64,mod=998244353;
const int inf=INT_MAX,INF=1e9+7; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
fuck int ls(int x){return x<<1;}
fuck int rs(int x){return x<<1|1;}
int sum[N<<2],lz[N<<2],cv[N<<2];
fuck void up(int rt){sum[rt]=(sum[ls(rt)]+sum[rs(rt)])%mod;}
fuck void down(int rt)
{
    if(cv[rt])
    {
        sum[ls(rt)]=sum[rs(rt)]=0;
        cv[ls(rt)]=cv[rs(rt)]=1;
        lz[ls(rt)]=lz[rs(rt)]=1;
        cv[rt]=0;
    }
    if(lz[rt]==1)return;
    sum[ls(rt)]=sum[ls(rt)]*lz[rt]%mod;
    sum[rs(rt)]=sum[rs(rt)]*lz[rt]%mod;
    lz[ls(rt)]=lz[ls(rt)]*lz[rt]%mod;
    lz[rs(rt)]=lz[rs(rt)]*lz[rt]%mod;
    lz[rt]=1;
}
fuck void cag(int rt,int l,int r,int p,int v)
{
    if(r<l)return;
    if(l==r){sum[rt]=v;return;}
    int mid=(l+r)>>1;
    down(rt);
    if(p<=mid)cag(ls(rt),l,mid,p,v);
    else cag(rs(rt),mid+1,r,p,v);
    up(rt);
}
fuck void qc(int rt,int L,int R,int l,int r,int v)
{
    if(r<l||R<L)return;
    if(l<=L&&R<=r)
    {
        sum[rt]=sum[rt]*v%mod;
        lz[rt]=lz[rt]*v%mod;
        return;
    }
    int mid=(L+R)>>1;
    down(rt);
    if(l<=mid)qc(ls(rt),L,mid,l,r,v);
    if(r>mid)qc(rs(rt),mid+1,R,l,r,v);
    up(rt);
}
fuck void cover(int rt,int L,int R,int l,int r)
{
    if(r<l||R<L)return;
    if(l<=L&&R<=r)
    {
        sum[rt]=0;cv[rt]=1;lz[rt]=1;return;
    }
    int mid=(L+R)>>1;
    down(rt);
    if(l<=mid)cover(ls(rt),L,mid,l,r);
    if(r>mid)cover(rs(rt),mid+1,R,l,r);
    up(rt);
}
fuck int query(int rt,int L,int R,int l,int r)
{
    if(r<l||R<L)return 0;
    if(l<=L&&R<=r)return sum[rt];
    int mid=(L+R)>>1;
    int ans=0;
    down(rt);
    if(l<=mid)ans=(ans+query(ls(rt),L,mid,l,r))%mod;
    if(r>mid)ans=(ans+query(rs(rt),mid+1,R,l,r))%mod;
    return ans;
}
int n,a,b,pos;
fuck void solve()
{
    memset(lz,1,sizeof(lz));
    cin>>n>>a>>b;pos=a;
    cag(1,1,a,pos,1);
    for(int i=1;i<=n;i++)
    {
        int l,r;cin>>l>>r;
        pos--;if(pos==0)pos=a;
        int lt_sum=query(1,1,a,1,a),val;
        if(l<=b)
        {
            val=(min(b,r)-l+1)*lt_sum%mod;
            cag(1,1,a,pos,val);
        }
        else cag(1,1,a,pos,0);
        if(r>b)
        {
            val=(r-max(b+1,l)+1);
            if(val<=0)
            {
                cover(1,1,a,1,pos-1);
                cover(1,1,a,pos+1,a);
            }
            else
            {
                qc(1,1,a,1,pos-1,val%mod);
                qc(1,1,a,pos+1,a,val%mod);
            }
        }
        else
        {
            cover(1,1,a,1,pos-1);
            cover(1,1,a,pos+1,a);
        }
    }
    cout<<query(1,1,a,1,a)<<endl;
}
signed main() 
{ 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int fuckccf=read();
    // int QwQ=read();
    // while(QwQ--)solve(); 
    solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666

T4. 洛谷 P11765 「KFCOI Round #1」回首

原题

在设计的向量不能很好推出矩阵时,尝试加一点其他限制进去。此处需要将 $ t $ 也加入向量,并用一个常数作为 $ t $ 增加的一个开关。

#include <bits/stdc++.h> 
#define i8  __int128
#define int long long 
#define fuck inline
#define lb long double 
using namespace std; 
// typedef long long ll; 
const int N=1e2+5,M=64,mod=998244353;
const int inf=INT_MAX,INF=1e9+7; 
// const int mod1=469762049,mod2=998244353,mod3=1004535809;
// const int G=3,Gi=332748118; 
// const int M=mod1*mod2;
fuck int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
    return x*f;
}
fuck void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int n,m,T;
int a[N+2][N+2],b[N+2][N+2],c[N+2][N+2];
int f[N+2],g[N+2];
fuck void fc1()
{
    memset(g,0,sizeof(g));
    for(int i=1;i<=n+2;i++)
        for(int j=1;j<=n+2;j++)g[i]=(g[i]+f[j]*b[j][i]%mod)%mod;
    for(int i=1;i<=n+2;i++)f[i]=g[i];
    // cout<<endl;
}
fuck void fc2()
{
    memset(c,0,sizeof(c));
    for(int k=1;k<=n+2;k++)
        for(int i=1;i<=n+2;i++)
            for(int j=1;j<=n+2;j++)c[i][j]=(c[i][j]+b[i][k]*b[k][j]%mod)%mod;
    for(int i=1;i<=n+2;i++)
        for(int j=1;j<=n+2;j++)b[i][j]=c[i][j];
}
int sum[N];
fuck void solve()
{
    memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(f,0,sizeof(f));
    cin>>n>>m>>T;
    for(int i=1;i<=n;i++)cin>>b[i][i];
    // for(int i=1;i<=n+2;i++)
    // {
    //     for(int j=1;j<=n+2;j++)cout<<b[i][j]<<" ";
    //     cout<<endl;
    // }
    // cout<<endl;
    for(int i=1;i<=m;i++)
    {
        int x,y;cin>>x>>y;
        b[x][y]=1;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(i==j)continue;
            sum[i]=(sum[i]+b[j][i]);
        }
    for(int i=1;i<=n;i++)if(!sum[i])b[n+1][i]=1,b[n+2][i]=1;
    b[n+1][n+1]=1;b[n+2][n+1]=1;b[n+2][n+2]=1;
    for(int i=1;i<=n+2;i++)
        for(int j=1;j<=n+2;j++)a[i][j]=b[i][j];
    // for(int i=1;i<=n+2;i++)
    // {
    //     for(int j=1;j<=n+2;j++)cout<<b[i][j]<<" ";
    //     cout<<endl;
    // }
    // cout<<endl;
    f[n+2]=1;
    while(T)
    {
        if(T&1)fc1();
        fc2();
        T>>=1;
    }
    
    for(int i=1;i<=n;i++)cout<<f[i]<<" ";
    cout<<"\n";
}
signed main() 
{ 
    // ios::sync_with_stdio(false); 
    // cin.tie(0); cout.tie(0); 
    // int fuckccf=read();
    // int QwQ=read();
    // while(QwQ--)solve(); 
    solve(); 
    return 0; 
}
//  6666   66666  666666 
// 6    6  6   6      6 
// 6    6  6666      6 
// 6    6  6  6    6 
//  6666   6   6  6666666




总结

  1. 对于动态规划的优化,首先需要得到合理的暴力,然后从拆贡献,单调性,是否符合一些数据结构的操作性质等方面进行优化;

完结收工!!!!!

个人主页

看完点赞,养成习惯

\(\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\)

posted @ 2025-07-11 22:47  Nightmares_oi  阅读(8)  评论(0)    收藏  举报