1. 程式人生 > 其它 >Codeforces Round #691 (Div. 2)ABC——解題報告

Codeforces Round #691 (Div. 2)ABC——解題報告

技術標籤:雜記演算法

比賽連結

https://codeforces.com/contest/1459

A - Red-Blue Shuffle

直接求出ai>bi和ai<bi的個數就行了,如果ai>bi比較多則輸出RED,如果ai<bi比較多則輸出BLUE,相等的話輸出EQUAL

證明:首先ai==bi的情況不用考慮,因為不論怎麼排列,對應位置都是相等的。

然後考慮ai>bi的情況,當ai和bi都在第一位時,RED的個數會加一,ai<bi的情況同理。

最後比較一下RED的個數和BLUE的個數就行了。

詳細證明參考題解:https://codeforces.com/blog/entry/85750

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
	return a/gcd(a,b)*b;
}
inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
const int N = 1e5+7;
int a[N],b[N];
void solve(){
	int n=read();
	string s1,s2;cin>>s1>>s2;
	int cnt1=0,cnt2=0;
	rp(i,0,n-1){
		if(s1[i]<s2[i]) cnt1++;
		if(s1[i]>s2[i]) cnt2++;
	}
	if(cnt1==cnt2) puts("EQUAL");
	else if(cnt1>cnt2) puts("BLUE");
	else puts("RED");
}
int main(){
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
	freopen("in.txt", "r", stdin);
	//debug = 1;
#endif
	time_t beg, end;
	//if(debug) beg = clock();

	int T=read();
	while(T--) solve();

	/*
	if(debug) {
		end = clock();
		printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
	}
	*/
	return 0;
}

B - Move and Turn

比賽時打了個前10的表,然後oeis了一發,按照上面的公式交了一發,沒想到過了。。

這個題由兩個做法:dp或者公式。

公式的證明參考題解,講的很詳細了。

公式的做法

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
	return a/gcd(a,b)*b;
}
inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
void solve(){
	ll n;scl(n);
	ll ans;
	if(n&1) ans=1+(3*n*(n+4)+2+(n*(n + 4)+2))/8;
	else ans=1+(3*n*(n+4)+2-(n*(n +4)+2))/8;
	cout<<ans<<endl;
}
int main(){
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
	// freopen("in.txt", "r", stdin);
	//debug = 1;
#endif
	time_t beg, end;
	//if(debug) beg = clock();
	solve();
	/*
	if(debug) {
		end = clock();
		printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
	}
	*/
	return 0;
}
/*
1 4
2 4
3 12
4 9
5 24
6 16
7 40
8 25
9 60
10 36
11 84
12 49
13 112
14 64
15 144
16 81
17 180
18 100
19 220
20 121
21 264
22 144
23 312
24 169
25 364
26 196
*/

C - Row GCD

比賽時打了個表,找到了迴圈節的假規律,不過迴圈節的長度一直找不到公式,然後這道題就沒了。

這個題的關鍵都基於一個公式(更相減損法):gcd(a,b)=gcd(a,b-a),這裡假設a<b。

首先可以知道一個公式:gcd(a,b,c)=gcd(gcd(a,b),c)=gcd(a,gcd(b,c)),這裡假設a<b<c。

那麼應用到多個變數的公式就是:

gcd(a,b,c)\Rightarrow gcd(a,gcd(b,c))\Rightarrow gcd(a,gcd(b,c-b))\Rightarrow gcd(a,b,c-b)\Rightarrow gcd(gcd(a,b),c-b)\Rightarrow gcd(gcd(a,b-a),c-b)

\Rightarrow gcd(a,b-a,c-b)

至於為什麼gcd(a,gcd(b,c-b))\Rightarrow gcd(a,b,c-b)是成立的?

首先可以知道gcd(a,gcd(b,c)))\Leftrightarrow gcd(a,gcd(b,c-b)),然後既然b和c的最大公約數等於b和c-b的最大公約數,因為我們最後還要和a再取一個最大公約數,那麼就可以用b和c-b替代b和c,反正他們兩個的作用都是提供他們倆的最大公約數,而且最大公約數都相等,所以為了方便可以進行替換。

這樣的話,對於題目給的公式我們就可以進行轉換,這裡預設a_{1}<=a_{2}<=...<=a_{n}

\gcd(a_1, a_2, \cdots, a_{n-2}, a_{n-1}, a_n) \\ \Rightarrow \gcd(a_1, a_2, \cdots, a_{n-2}, \gcd(a_{n-1}, a_n)) \\ \Rightarrow \gcd(a_1, a_2, \cdots, a_{n-2}, \gcd(a_{n-1}, a_n-a_{n-1})) \\ \Rightarrow \gcd(a_1, a_2, \cdots, a_{n-2}, a_{n-1}, a_n-a_{n-1}) \\ \Rightarrow \gcd(a_1, a_2, \cdots, \gcd(a_{n-2}, a_{n-1}), a_n-a_{n-1}) \\ \Rightarrow \gcd(a_1, a_2, \cdots, \gcd(a_{n-2}, a_{n-1}-a_{n-2}), a_n-a_{n-1}) \\ \Rightarrow \gcd(a_1, a_2, \cdots, a_{n-2}, a_{n-1}-a_{n-2}, a_n-a_{n-1}) \\ \cdots \\ \Rightarrow \gcd(a_1, a_2-a_1, \cdots, a_{n-1}-a_{n-2}, a_n-a_{n-1})

最終結果就是:

gcd(a_{1}+b_{j},a_{2}+b_{j},...,a_{n}+b_{j})\Rightarrow gcd(a_{1}+b_{j},a_{2}-a_{1},...,a_{n}-a_{n-1})

因此我們可以先對a陣列進行排序,然後再O(n)維護出gg=gcd(a_{2}-a_{1},...,a_{n}-a_{n-1})

再列舉b[j],最終答案就是gcd(gg,a_{1}+b_{j})

trick:注意gg要初始化為0,因為只有0能被其他所有數整除,1不符合條件,因為1不能被0整除。這裡有點不好理解。

其實也當時找的迴圈節的長度就是gcd(a_{2}-a_{1},...,a_{n}-a_{n-1}),不過找出來也會超時。

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
	return a/gcd(a,b)*b;
}
inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
const int N = 2e5+7;
ll a[N],b[N];
ll ans[N];
void solve(){
	int n=read(),m=read();
	rp(i,1,n) scl(a[i]);
	rp(i,1,m) scl(b[i]);
	sort(a+1,a+1+n);
	ll gg=0;
	rp(i,2,n) gg=gcd(gg,a[i]-a[i-1]);
	rp(j,1,m) printf("%lld%s",gcd(gg,a[1]+b[j]),j==m?"\n":" ");
}
int main(){
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
	freopen("in.txt", "r", stdin);
	//debug = 1;
#endif
	time_t beg, end;
	//if(debug) beg = clock();

	int T=1;
	while(T--) solve();

	/*
	if(debug) {
		end = clock();
		printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
	}
	*/
	return 0;
}