The 10th Henan Polytechnic University Programming Contest(Online mirror)

给您带来优质的代码体验,给您带来欢喜^_^

题面传送门

做一套有意思的题、领悟巧妙的算法难道不比玩游戏、看小说强上100倍?

A题

签到

B题

神奇!神奇!substr和优先队列真是神奇!AC的快乐才是真正的快了吧!

题目大意:

给你一个字符串S,问你长度为k且出现次数超过两次的子串有多少种,按字典序输出。

解题思路:先遍历一遍,并且用map计数,之后再遍历一遍,如果次数大于2,存入数组,并且次数置零。sort排序输出。

#include <iostream> 
#include <algorithm>
#include <map>
#include <cmath>
#include <cstring>
#include <queue>

using namespace std;

typedef long long ll;
//const int maxn=1;
//const int mod=1e9+7;

map<string,int> mp;
priority_queue<string,vector<string>,greater<string> > p; 

int main()
{
//	freopen("input.txt","r",stdin);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	string s;
	int k;
	cin>>s>>k;
	for(int i=0;i<s.length();i++)
	{
		string s2=s.substr(i,k);
		mp[s2]++;
	}
	for(int i=0;i<s.length();i++) 
	{
		string s3=s.substr(i,k);
		if(mp[s3]>2) 
		{
			mp[s3]=0;
			p.push(s3);
		}
	}
	cout<<p.size()<<endl;
	while(!p.empty())
	{
		string s4=p.top();
		p.pop();
		cout<<s4<<endl;
	}
	
	return 0;
}

1、做的过程中电脑出现问题,怀疑string不能有数组,后来发现原来行,觉着应该所有类型都能建数组。

2、啧啧,写这道题的时候忘记优先队列的头文件了,结果没用优先队列,其实。。。用万能头文件就行啊,亏我练了那么久的万能头文件。

D题

解题思路:

扫描二维码关注公众号,回复: 11173494 查看本文章

易知,一个点状态的改变取决于这个点的变化、所在行的变化、所在列的变化。

取一个点M为(x,y),则这个点所在的行和列都会发生变化。当Q个点取完之后,设点M出现的次数为a,点M所在行x出现的次数为b,点M所在列y出现的次数为c。则这个点的变化次数为(b-a)+(c-a)+a=b+c-a.

//#include <bits/stdc++.h>
#include <iostream> 
#include <algorithm>
#include <map>

using namespace std;
const int maxn=1e5+10;
map<int,int> mpx,mpy;
map<pair<int,int>,int> mpdot;//map中使用pair 

int main()
{
//	freopen("input.txt","r",stdin);
	int row,col,n;
	cin>>row>>col>>n;
	pair<int,int> Dot;//双int的pair类型Dot变量 
	for(int i=0;i<n;i++) 
	{
		int x,y;
		cin>>x>>y;
		mpx[x]++,mpy[y]++;
		Dot={x,y};
		mpdot[Dot]++;	
	} 
	int ans=0;
	for(int i=1;i<=row;i++)
	{
		for(int j=1;j<=col;j++)
		{
			Dot={i,j};
			int a=mpdot[Dot],b=mpx[i],c=mpy[j];
			if((b+c-a)%2==1) ans++;
		}
	}
	cout<<ans;
	
	return 0;
}

E题 

有规律,直接长度/2就行。

F题

题目大意:

你如果之前没看懂的话,估计是没有注意product这个词。这个词有“[数]乘积”的意思。

下次再一直看不懂题意,就要一个单词一个单词认真扣了。

解题思路:

模拟就行。

#include <iostream> 
#include <algorithm>
#include <map>
#include <cmath>

using namespace std;

typedef long long ll;
const int maxn=1e9+7;

int main()
{
	int n;
	cin>>n;
	ll ans=0;
	ll sum=1;
	for(int i=0;i<n;i++)
	{
		string s,s1;
		int a,b;
		cin>>s;
		if(s=="begin") continue;
		else if(s=="for")
		{
			cin>>s1;
			cin>>a>>b;
			sum*=(b-a+1);
			sum=sum%maxn;
		}
		else if(s=="end")
		{
			ans=(ans+sum)%maxn;
			sum=1;
		}
	}
	cout<<ans;
	
	return 0;
}

值得注意的是,我以为数很大需要用到大数取余呢。之前遇到说数很大要取余就很怕,结果这道题(可能很多题都这样),在分步进行的过程中分别取余就ok了,也是很欢喜了。

G题

看懂题意签到吧。

J题

题目大意:

给你一个数n,这个数化成二进制序列S,这个二进制序列复制n次成为序列T。问T中满足Ti=′1′,Tj=′1′,Tk=′0′,且1≤i<j<k≤|T|的

(i,j,k) 有多少组。

解题思路:

要求(i,j,k) 有多少组,可以从每个0前面有多少个1开始。对n除以2取二进制码,遇到0的时候,记录0的个数,同时使用map容器记录0前面1的个数、记录1的总个数sum。根据题意当一个0前面1的个数为a时,则对这个0来说,满足条件的组数为a*(a-1)。若第一组某个0满足条件的组数为a*(a-1),则第二组相应位置上的0满足条件的组数为(a+sum)*[(a+sum)-1],第三组相应位置上的0满足条件的组数为(a+2*sum)*[(a+2*sum)-1],后面的依次类推。

#include <iostream> 
#include <algorithm>
#include <map>
#include <cmath>
#include <cstring>

using namespace std;

typedef long long ll;
//const int maxn=1;
const int mod=1e9+7;

map<ll,ll> mp;//每个0前面1的个数 

int main()
{
//	freopen("input.txt","r",stdin);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	ll t;
	cin>>t;
	while(t--)
	{
		mp.clear();
		
		int n;
		cin>>n;
		ll sum0=0,sum1=0;
		ll m=n;
		while(m)
		{
			if(m%2==0) 
			{
				sum0++;//0的数目、下标从1开始 
			}
			else 
			{
				sum1++;
				for(ll i=1;i<=sum0;i++) mp[i]++;
			} 
			m/=2;
		}
		ll ans=0;
		for(ll i=1;i<=n;i++)
		{
			for(ll j=1;j<=sum0;j++)
			{
				ans=(ans+(mp[j]+(i-1)*sum1)*((mp[j]+(i-1)*sum1)-1)/2)%mod;
			}
		}
		cout<<ans%mod<<endl;
	}
	
	return 0;
}

哈哈,没想到我也有写出来这道题的时候。之前以为可难类,原来去尝试了,就变简单了。开始的时候n的值一直变化,变化到0了,给忘记了,结果错了。然后,map忘清零了,又错了。最后卡ll了,又错了。看来还是做题少,意识不够。多组数据输入,记得每次初始化,用到ll的地方一定要全部改成ll。把致错因素一开始就掌握到极致。总之,做出来这道题还是很高兴的,自信!

L题

(没时间了,不想写了,直接cv咯)

要使中的贡献最小,首先把除了第一项以外的值全部置为11,仅考虑第一项的值即可,假设表达式的值为00,计算出两个式子第一项值为a,ba,b,那么我们就进行如下操作:若其中一项不为正数,则两个数均加上一个值使得两个数均为正数。这样可以使得两个式子值相同且贡献尽可能的小。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2000000+10;
char s[maxn],t[maxn];
void solve(){
    int n;
    scanf("%d",&n);
    scanf("%s %s",s,t);
    int a=0,b=0;
    for(int i=0;i<n;i++){
        if(s[i]=='-') a++;
        else a--;
        if(t[i]=='-') b++;
        else b--;
    }
    int prea,preb;
    prea=a+max(1-min(a,b),0);
    preb=b+max(1-min(a,b),0);
 
    printf("%d %d\n",0,prea+preb+n*2);
 
    printf("%d",prea);
    for(int i=1;i<=n;i++) printf(" %d",1);
    printf("\n");
 
    printf("%d",preb);
    for(int i=1;i<=n;i++) printf(" %d",1);
    printf("\n");
}
int main()
{
    solve();
    return 0;
}

认真并快乐地过好生命中的每一分钟。

原创文章 99 获赞 15 访问量 7328

猜你喜欢

转载自blog.csdn.net/qq_45328552/article/details/103672867