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
总结
- 对于动态规划的优化,首先需要得到合理的暴力,然后从拆贡献,单调性,是否符合一些数据结构的操作性质等方面进行优化;
完结收工!!!!!

看完点赞,养成习惯
\(\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\)

浙公网安备 33010602011771号