河南萌新联赛2024第(二)场:南阳理工学院 (ADFHIJ)

题目来源:https://ac.nowcoder.com/acm/contest/87255

写在前面

今天的训练赛打的还行,发挥出我自己应有的水平,不过水平还是有限,该卡的地方还是卡着,有思路却写不出来是最难受的,还是得多刷刷题,提高代码水平

回归正题

按题目难度I、F、A、J、H、D、E顺序来展开

I- 重生之zbk要拿回属于他的一切

思路

签到题,暴力模拟即可

编程

void solve(){
	int n;cin >> n;
	string s;cin >> s;
	if(n<5){
		cout << 0 << endl;
		return ;
	}
	string s1="chuan";
	int sum=0;
	for(int i=0;i<=s.size()-5;++i){
		string s2=s.substr(i,5);
		if(s2==s1) sum++;
	}
	cout << sum;
	return ;
}

F-水灵灵的小学弟

思路

签到题,两人的缩写相同,直接输出DHY即可

编程

void solve(){
    int a,b;
    cin >> a >> b;
    cout << "DHY" << endl;
    return ;
}

A- 国际旅行Ⅰ

思路

签到题,将国家数量进行升序排序即可

编程

void solve(){
	int n,m,q;
	cin >> n >> m >> q;	
	for(int i=1;i<=n;++i) cin >> a[i];
	for(int i=1;i<=m;++i){
		int u,v;
		cin >> u >> v;
	}
	sort(a+1,a+1+n);
	while(q--){
		int x;cin >> x;
		cout << a[x] << endl;
	}
	return ;
}

J-这是签到

思路

暴力模拟,直接模拟1~5的行列式即可

编程

void solve(){
	int n,m;
	cin >> n >> m;
	for(int i=1;i<=n;++i)
	   for(int j=1;j<=m;++j){
	   	cin >> a[i][j];
	   }
	int minn=a[1][1];
	if(n==1&&m==1){
		cout << minn << endl;
		return ;
	}
	int k=a[1][1]*a[2][2]-a[1][2]*a[2][1];
	minn=min(k,minn);
	if(n<=2&&m<=2){
		cout << minn << endl;
		return ;
	}
	int k1=a[1][1]*a[2][2]*a[3][3]+a[1][2]*a[2][3]*a[3][1]+a[1][3]*a[2][1]*a[3][2];
	int k2=a[1][3]*a[2][2]*a[3][1]+a[1][1]*a[2][3]*a[3][2]+a[1][2]*a[2][1]*a[3][3];
	minn=min(minn,k1-k2);
	if(n<=3&&m<=3){
		cout << minn << endl;
		return ;
	}
	k1=a[1][1]*a[2][2]*a[3][3]*a[4][4]+a[1][2]*a[2][3]*a[3][4]*a[4][1]+a[1][4]*a[2][1]*a[3][2]*a[4][3]+a[1][3]*a[2][4]*a[3][1]*a[4][2];
	k2=a[1][4]*a[2][3]*a[3][2]*a[4][1]+a[1][1]*a[2][4]*a[3][3]*a[4][2]+a[1][3]*a[2][2]*a[4][4]*a[3][1]+a[1][2]*a[2][1]*a[3][4]*a[4][3];
	minn=min(minn,k1-k2);
	if(n<=4&&m<=4){
		cout << minn << endl;
		return ;
	}
	k1=a[1][1]*a[2][2]*a[3][3]*a[4][4]*a[5][5]+a[1][2]*a[2][3]*a[3][4]*a[5][1]*a[4][5]+a[1][5]*a[2][1]*a[3][2]*a[4][3]*a[5][4]+a[1][3]*a[2][4]*a[3][5]*a[4][1]*a[5][2]+a[1][4]*a[2][5]*a[3][1]*a[4][2]*a[5][3];
	k2=a[1][5]*a[2][4]*a[3][3]*a[4][2]*a[5][1]+a[1][1]*a[2][5]*a[3][4]*a[4][3]*a[5][2]+a[1][4]*a[2][3]*a[5][5]*a[3][2]*a[4][1]+a[1][2]*a[2][1]*a[3][5]*a[4][4]*a[5][3]+a[1][3]*a[2][2]*a[3][1]*a[4][5]*a[5][4];
	minn=min(minn,k1-k2);
	cout << minn << endl;
	return ;
}

H-狼狼的备忘录

思路

考点:暴力模拟,用map套set存姓名和信息,每次存入信息时对当前信息和set里面的信息进行比对,判断当前信息是否可以插入进去以及判断set里面的信息是否应当被排出去(判断后缀即可),最后从头遍历map输出就行

编程

void solve(){
	int n;cin >> n;
	map<string,set<string>> m;//set为了去重
	for(int i=0;i<n;++i){
		string s;int q;
		cin >> s >> q;
		while(q--){
			string x;cin >> x;
		    if(m[s].empty()) m[s].insert(x);
			else{
				int flag=1;//判断当前信息是否可以插入
				vector<string> r;//需要被排出去的信息
				for(auto t : m[s]){
					if(t.size()>=x.size()){
					int k=t.rfind(x);//必须反着找,正着找可能出现重复
				    if(k!=-1){
				      if(k+x.size()==t.size()) flag=0;	//判断后缀	
					 } 					 		    		
					}
					else{
						int k=x.rfind(t);
						if(k!=-1){
						if(k+t.size()==x.size()) r.push_back(t);	
						}
					}
				}
				if(flag) m[s].insert(x);
				if(!r.empty()){
				 for(auto c : r) 	m[s].erase(c);								
				}
			}
		}
	}
	cout << m.size() << endl;
	for(auto i : m){
		cout << i.fi << " " << i.se.size() << " ";
		for(auto j : i.se){
			cout << j << " ";
		}
		cout << endl;
	}
	return ;
}

D-A*BBBB

思路

考点:模拟+前缀和维护
由于b的每一位都相同,将b的每一位拆分,可以将a * b看作a * b[0] + a * b[0] * 10 + a * b[0] * 100···
即每多一个b的个数,就将a*b[0]整体向左移动一位
这时我们可以考虑用前缀和,先将a*b[0]进行前缀和处理,用两个指针来维护前缀和,然后模拟加法过程即可

编程

void solve(){
	string s1,s2;
	vector<int> a,b;
	cin >> s1 >> s2;
	int lena=s1.size();
	for(int i=s1.size()-1;i>=0;--i){
		a.push_back(s1[i]-'0');//高精度乘法倒着存入
	}
	int d=(s2[0]-'0');
	if(s1=="0" || d==0){//特判
		cout << 0 << endl;
		return ;
	}
	int t=0;
	for(int i=0;i<lena || t;++i){//将a*b[0]存入到数组里
		if(i<lena) t+=a[i]*d;
		b.push_back(t%10);
		t/=10;
	}
	while(b.size()>1 && b.back()==0) b.pop_back();//去除前导0
	int lenb=b.size();
	reverse(b.begin(),b.end());
	vector<int> sum(lenb+1),ans;
	for(int i=1;i<=lenb;++i) sum[i]=sum[i-1]+b[i-1];//前缀和
	int len=s2.size()+lenb-1;//最大长度为b的个数加上a*b[0]的长度
	int l=lenb+1,r=lenb;//双指针维护
	t=0;
	for(int i=len;i>=1;--i){
		r=min(i,r);//r指针取小
		if(l>1) l--;//l指针每次都往左移
		int num=sum[r]-sum[l-1];
		t+=num;
		ans.push_back(t%10);
		t/=10;
	}
	if(t) ans.push_back(t);
	reverse(ans.begin(),ans.end());
	for(auto i : ans) cout << i ;
	cout << endl;
	return ;
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值