CSP-J模拟赛五(补题2.0)

日期:2023.10.3

学号:s07661        

一.比赛概况:

总分400分,拿到220分,其中第1题100分,2题100分,3题20分,4题0分,

二. 比赛过程

前三题暴力枚举,第四题直接不会

三. 解题报告

一.重复判断

1.题目大意

小可需要判断一个字符串a,是否由另一个字符串b生成出来的,所谓的生成,其实就是把字符串b重复若干次,即:判断字符串a是否是字符串b重复若干次得到的。

2.比赛中的思考

新定义一个字符串,while(新字符串长度小于字符串a长度)拼接字符串b,判断拼接后是否等于字符串a

3.解题思路

上面思路,还可以while改for

4 .AC代码

#include<bits/stdc++.h>
using namespace std;
int t;
string s,s1;
int main(){

	cin>>t;
	while(t--){
		cin>>s>>s1;
		int x=s.size(),y=s1.size();
		if(x%y!=0){
			cout<<"NO";
			continue;
		}
		string s2="";
		while(s2.size()<s.size()){
			s2+=s1;
		}
		if(s2==s){
			cout<<"YES"<<"\n";
		}
		else{
			cout<<"NO"<<"\n";
		}
	}

	return 0;
}

二.歪果仁学乘法

1.题目大意

歪果仁不太会乘法,原因是他们被不过九九乘法表,小可听到之后,提出了一种不需要九九乘法表也可以计算乘法的方式,对于a × b:

1.将a,b的每一位上的数码画成线,不同位之间分隔开。
2.a 和 b 的方向垂直画出。
3.数出每个方向上交点的个数,即是 c 对应位置上的数码

求它们的乘积时交点的总个数是多少。

2.比赛中的思考

用两个循环求数位,两层循环逐位相乘,输出结果

3.解题思路

上面解法或如下:

cout<<(n%10*(m%10))+(n%10*(m/10))+(n/10*(m/10))+(n%10*(m/10));

4 .AC代码

自己的解法:

#include<bits/stdc++.h>
using namespace std;
int main(){
	
	int n,m,a[10],a1[10];
	cin>>n>>m;
	int t=n,t1=m,cnt=0,cnt1=0;
	while(t>0){
		a[++cnt]=t%10;
		t/=10;
	}
	while(t1>0){
		a1[++cnt1]=t1%10;
		t1/=10;
	}
	int sum=0;
	for(int i=1;i<=cnt;i++){
		for(int j=1;j<=cnt1;j++){
			sum+=a[i]*a1[j];
		}
	}
	cout<<sum;

	return 0;
}

正解:

#include<bits/stdc++.h>
using namespace std;
int main(){
	
	int n,m,a[10],a1[10];
	cin>>n>>m;
	cout<<(n%10*(m%10))+(n%10*(m/10))+(n/10*(m/10))+(n%10*(m/10));
	return 0;
}

三. 去重求和

1.题目大意

小可有一个长度为 n 的序列 a​i​​。他定义sum(l,r),为a[l] ~ a[r] ,这些数去重之后的和。请求出for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)sum(i,j);

2.比赛中的思考

暴力枚举

3.解题思路

定义桶,计算每个数第一次出现时产生的贡献。设为最大的,然后求出公式(n-i+1)*a[i]*(i-mp[a[i]])加到计数器中,再对桶进行标记,最后输出计数器中的值%1e9+7(最好是边计算边取余)

4 .AC代码

暴力如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,a[500005];
ll sum,ans;
const int mod=1e9+7;
map<ll,ll> mp;
int main(){
	cin>>n;
	for(ll i=1;i<=n;i++){
		cin>>a[i];
	}
	
	for(ll i=1;i<=n;i++){
		sum=0;
		for(ll j=i;j<=n;j++){
			if(mp.count(a[j])==0){
				sum+=a[j];
				mp[a[j]]=1;
			}
			ans=(sum+ans)%mod;	
		}
		mp.clear();
	}
	cout<<ans;
	return 0;
}

AC代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,a[500005],p[500005];
ll sum,ans;
const int mod=1e9+7;
map<ll,ll> mp;//定义桶 
int main(){
	cin>>n;//输入 
	for(ll i=1;i<=n;i++){
		cin>>a[i];
		mp[a[i]]=0;//桶标记 
	}
	
	for(int i=1;i<=n;i++){
		ans=ans+(n-i+1)%mod*a[i]%mod*(i-mp[a[i]])%mod;//计算公式 
		ans%=mod;//因为结果超过ll类型,所以一步取余一次 
		mp[a[i]]=i;//标记 
	}
	cout<<ans%mod;
	return 0;
}

四. 点集操作

1.题目大意

1.任选不同的两个点i,j
2.称 A​i​​ 为 i 能到达的所有点组成的点集,A​j​​ 为 j 能到达的所有点组成的点集 。(注意:每个点可以到达的点集包含这个点本身)
3.设 B 为一个最大的点集,满足 B 既是 A​i​​ 的子集,又是A​j​​的子集 。
4.将 B 在图中变成一个新点,B 内的所有边全部删除。点集 B 以外的点与点集 B 以内的点的连边关系转移到新点上。

2.比赛中的思考

不会怎么办??????

3.解题思路

图邻接表存储,遍历

4 .AC代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
vector<vector<int>> v;
vector<int> vis,ind;
int ans;
int n,k;
int main(){
	cin>>n>>k;//输入 
	v.resize(n+1);
	ind.resize(n+1);
	vis.resize(n+1);//初始大小 
	for(int i=1;i<=k;i++){
		int x,y;
		cin>>x>>y;
		v[x].push_back(y);//vector存储 
		++ind[y];
	}

	for(int i=0;i<v.size();i++){
		if(ind[i]){
			for(int j=0;j<v[i].size();j++){//遍历 
				vis[v[i][j]]=1;//标记没剩 
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(vis[i]==0)ans++;//判断是否剩下了 
	}
	cout<<ans;
	return 0;
}

总结:这几天模拟赛还行吧,但题难了就不知道变通,对知识点掌握的不熟悉,最后这15天要好好复习知识点,好好刷题,努力拿奖!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值