青岛市程序设计竞赛冲刺⑥(2023第四届上海市青少年算法竞赛小学组试题)

发布时间 2023-05-03 16:16:42作者: 天雷小兔

2.幸运数

原题:

 

原代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e7+5;
ll a[505]={0,6,8,66,68,86,88,666,668,686,688,866,868,886,888,6666,6668,6686,6688,6866,6868,6886,6888,8666,8668,8686,8688,8866,8868,8886,8888,66666,66668,66686,66688,66866,66868,66886,66888,68666,68668,68686,68688,68866,68868,68886,68888,86666,86668,86686,86688,86866,86868,86886,86888,88666,88668,88686,88688,88866,88868,88886,88888};
ll n,p=2;
string s[N],s1[N];
int main(){
//	freopen("T2.in","r",stdin);
//	freopen("T2.out","w",stdout);
	cin>>n;
	if(n<=62)cout<<a[n];
	else{
		s1[1]="6";
		s1[2]="8";
		while(n-p>0){
			n-=p;
			p*=2;
		}
		for(ll i=4;i<=p;i*=2){
			for(ll j=1;j<=i/2;j++)s[j]=(string)("6"+s1[j]);
			for(ll j=i/2+1;j<=i;j++)s[j]=(string)("8"+s1[j-i/2]);
			for(ll j=1;j<=i;j++)s1[j]=s[j];
		}
		cout<<s1[n];
	}
	return 0;
}

  

AC代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[67],x=2,n,len;
string ans;
int main(){
//	freopen("T2.in","r",stdin);
//	freopen("T2.out","w",stdout);
	cin>>n;
	a[1]=1;
	for(int i=2;i<=60;i++)x*=2,a[i]=x-1;
	for(int i=1;i<60;i++){
		if(n>=a[i]&&n<a[i+1]){
			len=i;
			n-=a[i];
			break;
		}
	}
	while(n>0){
		ans=char(n%2+48)+ans;
		n/=2;
	}
	int t=len-ans.length();
	for(int i=1;i<=t;i++)ans="0"+ans;
	for(int i=0;i<ans.length();i++){
		if(ans[i]=='0')cout<<6;
		else cout<<8;
	}
	return 0;
}

  

错误原因:

正解的规律是将幸运数字转换成二进制,而错解是运用组数的方法进行求解,所找的规律不同

 

3.连环画

原题:

 

 

原代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6+5,M = 3*N;
ll a[M],cnt[M];
int n,ans=0,Ok=0,t=1,n1;
bool p[M];
int main(){
//	freopen("T3.in","r",stdin);
//	freopen("T3.out","w",stdout);
	cin>>n;n1=n;
	for(int i=1;i<=n;i++)cin>>a[i],cnt[a[i]]++;
	while(t<=n1){
		Ok++;if(!p[a[t]])ans++;
		p[a[t]]=1;
		if(Ok>=2){
			int p=-1;
			for(int i=1;i<=3*n;i++){
				if(cnt[i]==0){
					p=i;
					break;
				}
			}
			if(p!=-1){
				a[++n1]=p;
				Ok-=2;
				cnt[p]++;
			}
		}
		t++;
	}
	cout<<ans;
	return 0;
}

  

AC代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e6+5;
int n,a[2*N],ans,sum;
int main(){
	cin>>n;
	for(int i=1,x;i<=n;i++)cin>>x,a[x]++;
	for(int i=1;i<=2*n;i++)if(a[i]>1)sum+=a[i]-1,a[i]=1;
	int j=2*n;
	for(int i=1;i<=2*n;i++){
		if(a[i]){
			ans=i;
			sum++;
		}else{
			if(sum>1){
				sum--;
				ans=i;
			}else{
				for(int k=j;k>i;k--){
					if(a[k]){
						sum++;
						a[k]=0;
						j=k;
						if(sum==2)break;
					}
				}
				if(sum==2){
					ans=i;
					sum=1;
				}else{
					cout<<ans;
					return 0;
				}
			}
		}
	}
	return 0;
}

  

错误原因:

考虑情况不周全,且条件不分明

 

4.团队竞赛

原题:

 

 

原代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e6+520;
pair<int,int>PI[N];
int n,X,a[N],k;
int main(){
//	freopen("T4.in","r",stdin);
//	freopen("T4.out","w",stdout);
	cin>>n>>X;
	for(int i=1;i<=n;i++)cin>>a[i];
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		for(int j=i+1;a[j]-a[i]<=X&&j<=n;j++){
			PI[++k].first=i;
			PI[k].second=j;
		}
	}
	cout<<ceil(k/3.0);
	return 0;
}

  

AC代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n,x,a[100005],last;
long long ans,m,s;
bool v[100005];
int main(){
	cin>>n>>x;
	for(int i=1;i<=n;i++)cin>>a[i];
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		int p=upper_bound(a,a+n+1,a[i]+x)-a;;
		if(v[p])continue;
		v[p]=1;
		if(last!=0)m=last-i;
		m=m*(m-1)*(m-2)/6;
		s=p-i;
		s=s*(s-1)*(s-2)/6;
		ans+=s-m;
		last=p;
	}
	cout<<ans;
	return 0;
}

  

错误原因:

根本性错误,没有想到区间和二分,思路不明确

 

5.集训题单

原题:

 

 

原代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3+5,MOD = 998244353;
ll n,m,k,X,a[N],sum=0,sum1=0;
ll add(ll a,ll b){return ((a%MOD)+(b%MOD))%MOD;}
int main(){
//	freopen("T5.in","r",stdin);
//	freopen("T5.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	cin>>k>>X;
	for(int i=1;i<=n;i++)if(a[i]>=X)sum++;
	for(int i=k;i<=m;i++)sum1=add(sum1,(m-i?(n-sum)*(sum-i+1):(sum-i+1)));
	cout<<sum1%MOD;
	return 0;
}

  

AC代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3+5,MOD = 998244353;
ll n,m,k,X,a[N],sum=0,sum1=0,c[N][N],ans=0;
ll add(ll a,ll b){return ((a%MOD)+(b%MOD))%MOD;}
int main(){
//	freopen("T5.in","r",stdin);
//	freopen("T5.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	cin>>k>>X;
	for(int i=1;i<=n;i++){
		if(a[i]>=X)sum++;
		else sum1++;
	}
	for(int i=0;i<=n;i++)c[i][0]=c[i][i]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<i;j++){
			c[i][j]=add(c[i-1][j-1],c[i-1][j]);
		}
	}
	for(int i=k;i<=sum;i++){
		if(i<=m){
			if(i==m)ans=add(ans,c[sum][i]);
			else ans=add(ans,c[sum][i]*c[sum1][m-i]);
		}
	}
	cout<<ans;
	return 0;
}

  

错误原因:

思路错误,正解运用杨辉三角求得组合数,统计两种情况后,运用乘法原理求解,而错解是累计个数的选法