Educational Codeforces Round 86 (Rated for Div. 2)

A 當b>2*a時每次只減一個數會花費更少,否則先同減到其中一個數爲0再計算會更少。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
int t,n,m;
ll x,y,a,b;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>x>>y>>a>>b;
		ll ans=0;
		ans+=min(x,y)*b;
		ans+=(max(x,y)-min(x,y))*a;
		cout<<min(ans,(x+y)*a)<<endl;
	}
	return 0;
}

B 如果t中只有一種字符那麼它的週期k就是1已經最小了直接輸出,否則週期不可能爲1,但是週期爲2是一定構造出來的,01交替即可,所以將相鄰的兩個相同字符中間加一個其他字符就可以了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1010;
int t,n,m;
string s,st;
int main(){
	cin>>t;
	while(t--){
		cin>>s;
		bool flag=1;
		for(int i=0;i<s.size()-1;i++)
			if(s[i]!=s[i+1])
			{
				flag=0;
				break;
			 } 
		if(!flag) 
		{
			for(int i=0;i<s.size();i++)
				if(i<s.size()-1)
				{
					st.push_back(s[i]);
					if(s[i]==s[i+1])
					{
						if(s[i]=='1') st.push_back('0');
						else st.push_back('1');
					}
				}
				else st.push_back(s[i]);
			cout<<st<<endl;
			st.clear();//記得清空
		}
		else cout<<s<<endl; 
	}
	return 0;
}

C 統計再區間[li,ri]之間x的個數,x滿足的條件是( (x%b)%a) != ( (x%a)%a)。
可以打表找規律:令Max=max(a,b),Lcm=lcm(a,b) , 滿足條件的x都有一個共性
x%Lcm在區間 [Max,Lcm)內。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1010;
int t,n,m,a,b;
string s,st;
ll get(ll l,int x,int y)//統計1到l滿足條件的個數
{
	return l/y*(y-x)+max(0ll,l%y-x+1);
}
int main(){
	cin>>t;
	while(t--){
		cin>>a>>b>>n;
		int x=max(a,b),y=a*b/__gcd(a,b);
		while(n--)
		{
			ll l,r;
			cin>>l>>r;
			cout<<get(r,x,y)-get(l-1,x,y)<<endl;
		}
	}
	return 0;
}

D 又是一道閱讀理解。已知一個測試樣例有n個數組,每個數組的長度不超過k,第i數組的長度是mi,讓你把這一個測試樣例分成多個,每個樣例中長度大於等於i的數組數量不超過ci。
因爲ci統計的是大於等於,所以先放長度最大的數組,這樣放的時候已經放過的數組長度一定大於等於當前數組,所以當放第i個數組時如果樣例中的數組數量a大於等於c[m[i]]時就不能放到這個樣例了,因爲放進去後大於等於m[i]的數量就是a+1一定大於等於c[m[i]]了,不滿足題意。
還要使測試樣例儘可能的少,所以就要讓每個樣例裏面儘可能多,但是會有一個最大限制c[1],因爲所有數組長度一定大於等於1,所以每個樣例最多有c[1]個數組。
每個樣例儘可能得多放,所以遍歷ans個樣例找第一個滿足(數組數量小於c[m[i]])的樣例,將m[i]放進去,如果找不到就再開一個樣例。暴力去找的話肯定會超時,我們每次都放到第一個滿足的樣例,所以前面的樣例數組會最多,後面的樣例數組會少,就是說數組數量是單減的,再單減序列中找第一個小於某個數的位置可以用二分,num[i]統計第i個樣例中數組數量的負值,找第一個大於 -c[m[i]]的位置就可以了,如果超出ans,就再加一個樣例。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200010;
int t,n,k,a,b;
int c[N],m[N];
vector<int> ve[N];
int num[N];
int ans=1;
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",m+i);
	for(int i=1;i<=k;i++) scanf("%d",c+i);
	sort(m+1,m+n+1);
	int l=1;//l表示還能放數組的最小樣例
	for(int i=n;i;i--)//倒序枚舉先放最大的
	{
		int x=upper_bound(num+l,num+ans+2,-c[m[i]])-num;//num[ans+1]=0,可以直接二分
		if(x<=ans)
		{
			ve[x].push_back(m[i]);
			num[x]--;
			if(ve[x].size()==c[1]) l=x+1;//最多可以放c[1]個
		}
		else ve[++ans].push_back(m[i]),num[x]--;
	}
	printf("%d\n",ans);
	for(int i=1;i<=ans;i++)
	{
		printf("%d ",ve[i].size());
		for(int j=0;j<ve[i].size();j++)
			printf("%d ",ve[i][j]);
		puts(""); 
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章