NOIP2024 前集训:多校A层冲刺NOIP2024模拟赛18
前言
不知道咋回事儿?脑子里一直放歌。
然后 T3 空间给了 256,开了 256.23 死了。
T1 选彩笔
显然可以二分答案,所以现在有了 \(O(nv^3\log v)\) 的做法,去重后可以拿到 \(80pts\),发现直接三维前缀和就可以做到 \(O(v^3\log v)\)。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=260;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,mx,ans,sum[N][N][N];
bool check(int mid)
{
for(int la=0,ra=mid+1;ra<=mx;la++,ra++)
for(int lb=0,rb=mid+1;rb<=mx;lb++,rb++)
for(int lc=0,rc=mid+1;rc<=mx;lc++,rc++)
if(sum[ra][rb][rc]-sum[la][rb][rc]-sum[ra][lb][rc]-sum[ra][rb][lc]+sum[la][lb][rc]+sum[la][rb][lc]+sum[ra][lb][lc]-sum[la][lb][lc]>=m)
return 1;
return 0;
}
signed main()
{
freopen("rgb.in","r",stdin),freopen("rgb.out","w",stdout);
read(n,m); for(int i=1,a,b,c;i<=n;i++)
read(a,b,c),sum[++a][++b][++c]++,mx=max({mx,a,b,c});
for(int i=1;i<=mx;i++) for(int j=1;j<=mx;j++) for(int k=1;k<=mx;k++)
sum[i][j][k]+=sum[i-1][j][k]+sum[i][j-1][k]+sum[i][j][k-1]-sum[i-1][j-1][k]-sum[i-1][j][k-1]-sum[i][j-1][k-1]+sum[i-1][j-1][k-1];
for(int l=0,r=mx,mid;l<=r;)
{if(check(mid=l+r>>1)) r=mid-1,ans=mid; else l=mid+1;}
write(ans);
}
T2 兵蚁排序
高级构造题,赛时没看,但是发现他都说了操作数不大于 \(n^2\) 就行,明摆着冒泡。
发现如果出现 \(b\) 中没有但是 \(a\) 中有的逆序对就无解,其余的直接冒泡即可。
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=1010;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int T,n,a[N],b[N]; vector<pair<int,int> >ans;
signed main()
{
freopen("sort.in","r",stdin),freopen("sort.out","w",stdout);
for(read(T);T;T--,ans.clear())
{
read(n); bool flag=0;
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=n;i++) read(b[i]);
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
if(a[j]<b[i]) {flag=1,i=n; break;}
else if(a[j]==b[i])
{
for(int k=j;k>i;k--)
swap(a[k-1],a[k]),ans.push_back(make_pair(k-1,k));
break;
}
}
}
if(flag) {puts("-1"); continue;}
puts("0"),write(ans.size()),puts("");
for(auto pos:ans) write(pos.first,pos.second),puts("");
}
}
T3 人口局 DBA
数位 DP 好题,直接上数位 DP,如果是递归的因为记忆化数组开不下分数不高,改成递推的能滚动一下就有 \(60\) 多分,加一些优化,只记录不是 \(limit\) 状态下的,这部分可以递推跑,跑出来的有用的就丢进去递归,这样能防止空间爆炸,有 \(91pts\),再发现其本质,把递归那部分改成递推直接跑,就有了 \(97pts\)。
放一些代码
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=2010,M=510,P=1e9+7,S=5e4+10;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,s,a[N],f[M][S],g[N][N<<1];
inline int mod(int x,int y) {return (x+=y)>=P?x-P:x;}
inline int dfs(int len,int sum,bool limit,bool flag)
{
if(sum>s||sum+(n-len+1)*(m-1)<s) return 0;
if(len==n+1) return (sum==s);
if(flag&&!limit&&f[len][sum]!=-1) return f[len][sum];
int maxx=limit?a[len]:m-1,ans=0;
if(flag) for(int i=0;i<=maxx;i++)
ans=mod(ans,dfs(len+1,sum+i,limit&&(i==maxx),1));
else
{
for(int i=1;i<=maxx;i++)
ans=mod(ans,dfs(len+1,sum+i,limit&&(i==maxx),1));
ans=mod(ans,dfs(len+1,0,0,0));
}
if(!limit) f[len][sum]=ans;
return ans;
}
inline int dfs2(int len,int sum,bool limit,bool flag)
{
if(sum>s||sum+(n-len+1)*(m-1)<s) return 0;
if(len==n+1) return (sum==s);
if(flag&&!limit&&g[len][sum]!=-1) return g[len][sum];
int maxx=limit?a[len]:m-1,ans=0;
if(flag) for(int i=0;i<=maxx;i++)
ans=mod(ans,dfs2(len+1,sum+i,limit&&(i==maxx),1));
else
{
for(int i=1;i<=maxx;i++)
ans=mod(ans,dfs2(len+1,sum+i,limit&&(i==maxx),1));
ans=mod(ans,dfs2(len+1,0,0,0));
}
if(!limit) g[len][sum]=ans;
return ans;
}
signed main()
{
freopen("dba.in","r",stdin),freopen("dba.out","w",stdout);
read(m,n),memset(f,-1,sizeof(f)),memset(g,-1,sizeof(g));
for(int i=1;i<=n;i++) read(a[i]),s+=a[i];
if(s<=2*m) write(dfs2(1,0,1,0)-1);
else write(dfs(1,0,1,0)-1);
}
#include<bits/stdc++.h>
#pragma GCC optimize(3)
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=2010,M=4e6+10,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,s,a[N],f[2][M][2];
inline int mod(int x,int y) {return (x+=y)>=P?x-P:x;}
signed main()
{
freopen("dba.in","r",stdin),freopen("dba.out","w",stdout);
read(m,n);
for(int i=1;i<=n;i++) read(a[i]),s+=a[i]; reverse(a+1,a+1+n);
f[0][s][0]=f[0][s][1]=1;
for(int i=1,x=1,y=0;i<=n;i++,x^=1,y^=1)
{
for(int j=0;j<=min(s,(n-i+2)*(m-1));j++)
f[x][j][0]=f[x][j][1]=0;
for(int j=0;j<=min(s,(n-i+1)*(m-1));j++)
{
for(int k=0;k<=min(a[i]-1,s-j);k++)
{
f[x][j][0]=mod(f[x][j][0],f[y][j+k][0]);
f[x][j][1]=mod(f[x][j][1],f[y][j+k][0]);
}
f[x][j][1]=mod(f[x][j][1],f[y][j+a[i]][1]);
for(int k=a[i];k<=min(m-1,s-j);k++)
f[x][j][0]=mod(f[x][j][0],f[y][j+k][0]);
}
}
write(f[n&1][0][1]-1);
}
#include<bits/stdc++.h>
#include<bits/extc++.h>
#pragma GCC optimize(3)
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
using namespace __gnu_pbds;
const int N=2000+1,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,s,a[N],f[2][N*N]; unordered_map<int,int>mp[N];
inline int mod(int x,int y) {return (x+=y)>=P?x-P:x;}
inline void dfs(int len,int sum,bool lim)
{
if(sum+len*(m-1)<s) return ;
if(!lim) return mp[len][s-sum]=0,void();
int maxx=lim?a[len]:m-1;
for(int i=0;i<=maxx&&sum+i<=s;i++) dfs(len-1,sum+i,lim&&(i==maxx));
}
inline int dp(int len,int sum,bool lim)
{
if(!len) return sum==s;
if(!lim) return mp[len][s-sum];
int res=0,maxx=lim?a[len]:m-1;
for(int i=0;i<=maxx&&sum+i<=s;i++)
res=mod(res,dp(len-1,sum+i,lim&&(i==maxx)));
return res;
}
signed main()
{
freopen("dba.in","r",stdin),freopen("dba.out","w",stdout);
read(m,n); for(int i=n;i;i--) read(a[i]),s+=a[i];
dfs(n,0,1),f[0][0]=1;
for(int i=1,x=1,y=0;i<=n;i++,x^=1,y^=1) for(int j=0;j<=s;j++)
{
f[x][j]=f[y][j],(j)&&(f[x][j]=mod(f[x][j],f[x][j-1]));
(j>=m)&&(f[x][j]=mod(f[x][j],P-f[y][j-m]));
if(mp[i].find(j)!=mp[i].end()) mp[i][j]=f[x][j];
}
write(dp(n,0,1)-1);
}
#include<bits/stdc++.h>
#pragma GCC optimize(3)
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=2000+1,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,sum,ans,a[N],f[2][N*N];
inline int mod(int x,int y) {return (x+=y)>=P?x-P:x;}
signed main()
{
freopen("dba.in","r",stdin),freopen("dba.out","w",stdout);
read(m,n); for(int i=1;i<=n;i++) read(a[i]),sum+=a[i];
f[0][0]=1; for(int i=1,x=1,y=0,s=a[n];i<=n;s+=a[n-i],i++,x^=1,y^=1)
{
for(int j=0;j<=sum;j++)
{
f[x][j]=f[y][j],(j)&&(f[x][j]=mod(f[x][j],f[x][j-1]));
(j>=m)&&(f[x][j]=mod(f[x][j],P-f[y][j-m]));
}
for(int j=0;j<a[n-i+1];j++) ans=mod(ans,f[y][s-j]);
}
write(ans);
}
正解加个容斥就可以了,推推式子,但我懒得再写一遍了,沾官方题解了:
点击查看代码
#include<bits/stdc++.h>
#pragma GCC optimize(3)
#define ll long long
#define endl '\n'
#define sort stable_sort
using namespace std;
const int N=2010,P=1e9+7;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool z=true;
register char c=getchar_unlocked();
for(;!isdigit(c);c=getchar_unlocked()) if(c=='-') z=0;
for(;isdigit(c);c=getchar_unlocked()) x=(x<<1)+(x<<3)+(c^48);
x=(z?x:~x+1);
}
template<typename T,typename ...Tp> inline void read(T &x,Tp &...y){read(x);read(y...);}
template<typename Tp> inline void wt(Tp x){if(x>9)wt(x/10);putchar_unlocked((x%10)+'0');}
template<typename Tp> inline void write(Tp x){if(x<0)putchar_unlocked('-'),x=~x+1;wt(x);}
template<typename T,typename ...Tp> inline void write(T x,Tp ...y){write(x);putchar_unlocked(' ');write(y...);}
int n,m,s,ans,a[N],jc[N*N],inv[N*N];
inline int mod(int x,int y) {return (x+=y)>=P?x-P:x;}
inline int qpow(ll a,int b,ll res=1)
{for(;b;(a*=a)%=P,b>>=1) (b&1)&&((res*=a)%=P); return res;}
inline int C(int n,int m) {return m>n?0:1ll*jc[n]*inv[n-m]%P*inv[m]%P;}
inline int solve(int n,int s,int a,int res=0)
{
for(int i=0;i<=n;i++)
res=mod(res,1ll*mod((i&1?-1ll:1ll)*C(n,i)*(C(s-i*m+n,n)-C(s-a-m*i+n,n))%P,P));
return res;
}
signed main()
{
freopen("dba.in","r",stdin),freopen("dba.out","w",stdout);
read(m,n); for(int i=1;i<=n;i++) read(a[i]),s+=a[i];
jc[0]=1; for(int i=1;i<=n*m;i++) jc[i]=1ll*jc[i-1]*i%P;
inv[n*m]=qpow(jc[n*m],P-2);
for(int i=n*m-1;~i;i--) inv[i]=1ll*inv[i+1]*(i+1)%P;
for(int i=1,j=0;i<=n;j+=a[i++]) ans=mod(ans,solve(n-i,s-j,a[i]));
write(ans);
}
T4 银行的源起
不会。