NOIP2021模拟赛10.12 题解


写在前面的话

最近写题的状态一直不在,写什么都挂,想法也有漏洞

T1

A. 「NOIP2021模拟赛五 A」Generator

通过观察我们发现,将数列从大到小排序后,遇到的一个数

  • 如果他是一个素数,那么肯定是第 \(i\) 个素数演化而来的

  • 如果是一个合数,那么肯定是要分解的

因为 \(i\) 始终小于第 \(i\) 个素数,一个数的因数必定小于他本身

#include<bits/stdc++.h>
using namespace std;
const int maxn=4e5+5,maxm=2750135;
int N,a[maxn],b[maxn],p[maxm],max_x,prm[maxm],vis[maxm],Q[maxm];
struct IO{
    static const int S=1<<21;
    char buf[S],*p1,*p2;int st[105],Top;
    ~IO(){clear();}
    inline void clear(){fwrite(buf,1,Top,stdout);Top=0;}
    inline void pc(const char c){Top==S&&(clear(),0);buf[Top++]=c;}
    inline char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    inline IO&operator >> (char&x){while(x=gc(),x==' '||x=='\n'||x=='r');return *this;}
    template<typename T>inline IO&operator >> (T&x){
        x=0;bool f=0;char ch=gc();
        while(ch<'0'||ch>'9'){if(ch=='-') f^=1;ch=gc();}
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=gc();
        f?x=-x:0;return *this;
    }
    inline IO&operator << (const char c){pc(c);return *this;}
    template<typename T>inline IO&operator << (T x){
        if(x<0) pc('-'),x=-x;
        do{st[++st[0]]=x%10,x/=10;}while(x);
        while(st[0]) pc('0'+st[st[0]--]);return *this;
    }
}fin,fout;
inline void make_p(){
	for(int i=2;i<=max_x;i++){
		if(Q[i])continue;
		p[++p[0]]=i;prm[i]=p[0];
		for(int j=1;j*i<=max_x;j++){
			Q[i*j]=1;
		}
	}
	return ;
}
int max_p(int x){
	int sq=sqrt(x);
	for(int i=2;i<=sq;i++){
		if(x%i==0)return x/i;
	}
}
int main(){
	fin>>N;
	for(int i=1;i<=(N<<1);i++)fin>>b[i],vis[b[i]]++,max_x=max(max_x,b[i]);
	make_p();
	sort(b+1,b+1+(N<<1));
	for(int i=(N<<1);i;i--){
		if(!vis[b[i]])continue;
		if(prm[b[i]]&&vis[prm[b[i]]]){
			a[++a[0]]=prm[b[i]];
			vis[b[i]]--;vis[prm[b[i]]]--;
		}
		else{
			int now=max_p(b[i]);
			if(vis[now]){
				a[++a[0]]=b[i];
				vis[b[i]]--;vis[now]--;
			}
		}
	}
	sort(a+1,a+1+a[0]);
	for(int i=1;i<=a[0];i++){
		if(i!=a[0])fout<<a[i]<<' ';
		else fout<<a[i];
	}
	return 0;
}

T2

B. 「NOIP2021模拟赛五 B」Data deletion

我们先思考这个问题的弱化版,只有 \(AB\)

我们发现每次删除 \(AA\)\(BB\) 也就是一个奇数位上的 \(A\) 和偶数位上的\(A\) ,\(B\) 同理

那么显然奇数位上 \(A\) 的个数 \(=\) 偶数位上 \(A\) 的个数 ,\(B\) 同理

那么我们将奇数位上的 \(A\) 换成 \(B\), \(B\) 换成 \(A\) ,那么就变成 \(A\) 的个数等于 \(B\) 的个数,这一步很关键

由于修改后的串能和修改前的串一一对应,所以只需要求修改后串的个数就好了

我们可以枚举 \(A\) 的个数,就可以得出 \(B\) 的个数和 \(C\) 的个数,但是这样会算重

考虑用补集思想,用总的个数减去不可能的个数,显然当 \(A\) 的个数 \(>n/2\) 时是不可能的

所以枚举 \(A\) 的个数 \(i\),不可能的个数就是\(C_{n}^i\times 2^{n-i}\)

\(i\) 个随便排,剩下的 \(n-i\) 个放 \(C\)\(B\)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e7+5;
const LL TT=998244353;
int N;
LL Fct[maxn],iFct[maxn],ans;
LL Pow(LL a,LL b){LL s=1,w=a;while(b){if(b&1)s=s*w%TT;w=w*w%TT;b>>=1;}return s;}
LL C(LL x,LL y){
	return Fct[x]*iFct[y]%TT*iFct[x-y]%TT;
}
int main(){
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
	cin>>N;
	Fct[0]=1;for(int i=1;i<=N;i++)Fct[i]=Fct[i-1]*i%TT;
	iFct[N]=Pow(Fct[N],TT-2);for(int i=N-1;~i;i--)iFct[i]=iFct[i+1]*(i+1)%TT;
	for(int i=(N>>1)+((N&1)==0);i<=N;i++){
		ans=(ans+C(N,i)*Pow(2,N-i)%TT)%TT;
	}
	ans=((Pow(3ll,N)-(ans<<1))%TT+TT)%TT;
	cout<<ans<<endl;
	return 0;
}

T3

C. 「NOIP2021模拟赛五 C」Play dominos

一道质量不是很高的构造题

我们手玩出 \(3,5,7\) 的情况

然后对于奇数,我们需要算出 \(n-5\) 的答案然后加上 \(5\) 的答案

对于偶数,我们将用\(n\%6\)分类

  • \(n\%6=0\)
x.aa......z.
x.bb......z.
y.cc......y.
y...aa....y.
z...bb....x.
z...cc....x.
.x....aa...z
.x....bb...z
.y....cc...y
.y......aa.y
.z......bb.x
.z......cc.x
  • \(n\%6=2\)
x.aa.......p..
x.bb.......p..
y..cc.......z.
y...aa......z.
z...bb......y.
z....cc.....y.
.x....aa....x.
.x....bb....x.
.y.....cc....z
.y......aa...z
.z......bb...y
.z.......cc..y
..p.......aa.x
..p.......bb.x
  • \(n%6=4\)
x.aa.........q..
x..bb........q..
y..cc........p..
y...aa.......p..
z....bb.......z.
z....cc.......z.
.x....aa......y.
.x.....bb.....y.
.y.....cc.....x.
.y......aa....x.
.z.......bb....z
.z.......cc....z
..p.......aa...y
..p........bb..y
..q........cc..x
..q.........aa.x

X朋的代码:

#include<bits/stdc++.h>
using namespace std;
char 
A3[3][4]={"aab","b.b","baa"},
A4[4][5]={"aacd","bbcd","cdaa","cdbb"},
A5[5][6]={"aabba","b.cca","bd..b","ad..b","abbaa"},
A6[6][7]={"aabcc.","b.b..d","baa..d","cc.aab","..db.b","..dbaa"},
A7[7][8]={"aabb..x","b..cc.x","ba....y",".a..aay","..a..bz","..a..bz","xxyyzz."},
A8[8][9]={"abb...a.","acc...a.","b.aa...c","b..bb..c","c..cc..b","c...aa.b",".a...bba",".a...cca"};
const int N=1005;
char ans[N][N];bool flg;
int main(){
	int n;scanf("%d",&n);if(n<=2) return puts("-1")&0;
	if(n<=7){
		if(n==3) for(int i=0;i<3;i++) printf("%s\n",A3[i]);
		if(n==4) for(int i=0;i<4;i++) printf("%s\n",A4[i]);
		if(n==5) for(int i=0;i<5;i++) printf("%s\n",A5[i]);
		if(n==6) for(int i=0;i<6;i++) printf("%s\n",A6[i]);
		if(n==7) for(int i=0;i<7;i++) printf("%s\n",A7[i]);
		return 0;
	}else{
		if(n&1){
			n-=5;flg=1;
		}
		if(n%6==0) for(int t=0;t<n/6;t++){
			for(int i=0;i<6;i++)
			for(int j=0;j<6;j++) ans[t*6+i][t*6+j]=A6[i][j];
		}else for(int t=0;t<n/6;t++){
			for(int i=0;i<6;i++)
			for(int j=0;j<6;j++) ans[t*6+i][t*6+j]=A6[i][j];
		}
		if(n%6==2)
			for(int i=0;i<8;i++)
			for(int j=0;j<8;j++) ans[n/6*6-6+i][n/6*6-6+j]=A8[i][j];
		if(n%6==4)
			for(int i=0;i<4;i++)
			for(int j=0;j<4;j++) ans[n/6*6+i][n/6*6+j]=A4[i][j];
		if(flg){
			for(int i=0;i<5;i++)
			for(int j=0;j<5;j++) ans[n+i][n+j]=A5[i][j];
			n+=5;
		}
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++) if(!ans[i][j]) ans[i][j]='.';
		printf("%s\n",ans[i]);
	}
	return 0;
}

T4

D. 「NOIP2021模拟赛五 D」Conjoint

题解


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM