[整理]NOIP2021 题解
T1
秒了,直接写一个线性筛一样的东西即可。
const int N=10000010;
int T,x;
bool ok[N];int nxt[N];
il void Init(){
for(int i=1;i<N;i++){
if(ok[i])continue;
int t=i;bool ff=0;
while(t){
if(t%10==7){
ff=1;break;
}
t/=10;
}
if(ff)for(int j=i;j<N;j+=i)ok[j]=1;
}
//lst: 上一个 0
for(int i=1,lst=0;i<N;i++){
if(ok[i])continue;
nxt[lst]=i,lst=i;
}
}
void Print(int x){
if(x>9)Print(x/10);
putchar(x%10+48);
}
int main(){
Init(),Read(T);
while(T--){
Read(x);
if(!nxt[x])puts("-1");
else Print(nxt[x]),putchar('\n');
}
KafuuChino HotoKokoa
}
T2
题面看起来很麻烦,其实转化成 \(m+1\) 个位置放 \(n\) 个数就很好做了(也就是看从 \(0\) 到 \(m\) 的每个数在 \(a\) 中出现多少次),可以直接设 \(f_{i,j,k,l}\) 表示放到第 \(i\) 位、放了 \(j\) 个、进位 \(k\)、共有 \(l\) 个 \(1\) 时的方案数,转移时乘上系数。
const int N=35,M=110,p=998244353;
int n,m,K,v[M],fac[N],inv[N];
il int Pow(int a,int b=p-2){
int res=1;
for(;b;a=(LL)a*a%p,b>>=1)if(b&1)res=(LL)res*a%p;
return res;
}
int C[N][N];
int f[M][N][N][M];
int main(){
Read(n),Read(m),Read(K),C[0][0]=1;
for(int i=0;i<=m;i++)Read(v[i]);
for(int i=1;i<=n;i++){
C[i][0]=1;
for(int j=1;j<=i;j++){
C[i][j]=(C[i-1][j]+C[i-1][j-1])%p;
}
}
for(int i=0;i<=n;i++){
f[0][i][i/2][i%2]=(LL)C[n][i]*Pow(v[0],i)%p;
}
for(int i=0;i<m;i++){
for(int j=0;j<=n;j++){
for(int k=0;k<=j/2;k++){
for(int l=0;l<=min(i+1,j);l++){
if(!f[i][j][k][l])continue;
for(int t=0;j+t<=n;t++){
//i+1 rT rfT t Vga
(f[i+1][j+t][k+t>>1][l+(k+t)%2]+=(LL)\
f[i][j][k][l]*C[n-j][t]%p*Pow(v[i+1],t)%p)%=p;
}
}
}
}
}
int ans=0;
for(int k=0;k<=n/2;k++){
for(int l=0;l<=min(m+1,n);l++){
if(__builtin_popcount(k)+l<=K){
(ans+=f[m][n][k][l])%=p;
}
}
}
printf("%d\n",ans);
KafuuChino HotoKokoa
}
T3
观察题目中的操作,发现其实是交换两个差分值,猜一手结论差分数组应该是单谷。
所以我们可以把差分数组 \(d\) 从小到大往两边加,可以通过 dp 来实现,状态需要记录上当前的 \(a\) 之和。
一眼看上去好像是差分值个数 \(n\) 乘上最大的 \(a\) 之和 \(nV\) 的?不过发现一个细节就是 \(n\) 最大的一档部分分 \(V\) 非常小,也就意味着差分值有贡献(大于零)的个数不会特别多,仍然是 \(O(V)\) 级别的,所以复杂度正确。
const int N=10010,M=610;
int n,a[N],d[N],f[N*M];
il void Mn(int &a,int b){
a=b<a?b:a;
}
signed main(){
Read(n);
for(int i=1;i<=n;i++)Read(a[i]),d[i-1]=a[i]-a[i-1];
sort(d+1,d+n);
int na=0,V=0;//dTjuV $\sum d_i$ / zVdaVH6
memset(f,0x3f,sizeof f),f[0]=0;
for(int i=1;i<n;i++){
if(!d[i])continue;
for(int j=V;j>=0;j--){
if(f[j]==INF)continue;
int fj=f[j];f[j]=INF;
//Eti2ja FLH robie
Mn(f[j+i*d[i]],fj+2*d[i]*j+i*d[i]*d[i]);
//Eti2ja FLH 7i6bie
Mn(f[j+na+d[i]],fj+(na+d[i])*(na+d[i]));
}
na+=d[i],V+=i*d[i];
}
int ans=INF;
for(int i=V;i>=0;i--)if(f[i]!=INF)Mn(ans,n*f[i]-i*i);
printf("%lld\n",ans);
KafuuChino HotoKokoa
}
T4
快退役了翻草稿箱翻到这玩意,早就忘了这题是啥了,先咕咕着。
内容来自_ajthreac_的博客(https://www.cnblogs.com/juruoajh/),未经允许,不得转载。