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題

解題思路:

易知,一個點狀態的改變取決於這個點的變化、所在行的變化、所在列的變化。

取一個點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;
}

 

 

 

 

 

 

 

 

認真並快樂地過好生命中的每一分鐘。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章