Codeforces Round #677 (Div. 3)(A->E(排列組合))
A:http://codeforces.com/contest/1433/problem/A
解析:
直接手寫個表,一個一個算就行了。
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e5 + 95; int num[9999]={0,1,11,111,1111,2,22,222,2222,3,33,333,3333,4,44,444,4444,5,55,555,5555,6,66,666,6666,7,77,777,7777, 8,88,888,8888,9,99,999,9999}; int main() { int t; cin>>t; while(t--) { int x; cin>>x; int cnt=0; for(int i=1;;i++) { if(i%4==1) cnt++; else if(i%4==2) cnt+=2; else if(i%4==3) cnt+=3; else cnt+=4; if(num[i]==x) { break; } } cout<<cnt<<endl; } }
B:http://codeforces.com/contest/1433/problem/B
題意:
對於[L,R]如果裡面全是1,而且L-1是0或R+1是0,就可以整體左移或右移。
求使整個陣列無0間隔的最小移動數。
解析:
先找到第一個1,從這裡開始遍歷
如果這一位是1,下一位是0,就往後找1,找到就加間距
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e5 + 95; int num[9999]={0,1,11,111,1111,2,22,222,2222,3,33,333,3333,4,44,444,4444,5,55,555,5555,6,66,666,6666,7,77,777,7777, 8,88,888,8888,9,99,999,9999}; int a[66]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; int maxx=0; int ok=0; int id; for(int i=1;i<=n;i++) { if(a[i]==1) { id=i;break; } } int sum=0; for(int i=id;i<=n;i++) { if(a[i]==1&&a[i+1]==0) { int mdid; for(int j=i+2;j<=n;j++) { if(a[j]==1) { sum+=j-i-1; break; } } } } cout<<sum<<endl; } }
C:http://codeforces.com/contest/1433/problem/C
題意:
如果一個食人魚,比左邊或右邊大,就可以吃掉左邊或右邊那條,自身+1
是否存在這麼一條食人魚,每次都讓它吃,使得最後只剩它一條?
解析:
全相等肯定不存在。否則一定存在
先找出最大值,再遍歷一次,如果存在某個值等於最大值,而且左邊或右邊魚與它不相等,就輸出它即可。
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 3e5 + 95; int num[9999]={0,1,11,111,1111,2,22,222,2222,3,33,333,3333,4,44,444,4444,5,55,555,5555,6,66,666,6666,7,77,777,7777, 8,88,888,8888,9,99,999,9999}; ll a[maxn]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; cin>>a[1]; ll maxx=a[1]; int ok=0; for(int i=2;i<=n;i++) { cin>>a[i]; maxx=max(maxx,a[i]); if(a[i]!=a[i-1]) ok=1; } if(!ok) cout<<"-1"<<endl; else { int idx; a[n+1]=a[n]; for(int i=n;i>=1;i--) { if(a[i]==maxx&&(a[i]!=a[i-1]||a[i]!=a[i+1])) { idx=i; break; } } cout<<idx<<endl; } } }
D:http://codeforces.com/contest/1433/problem/D
題意:
n個組,ai表示其所屬幫派。
用n-1條邊,使得每個組之間可以互相到達。如果兩個同幫派直接相連,那麼就會發生衝突。
是否存在一種連線方式,避免這種情況?
解析:
1:全都屬於一個幫派,肯定不存在。
2:想象成衛星圖
找兩個不相等的ai,連一起,其他的ai往它倆上連即可。
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 5e3 + 95; int num[9999]={0,1,11,111,1111,2,22,222,2222,3,33,333,3333,4,44,444,4444,5,55,555,5555,6,66,666,6666,7,77,777,7777, 8,88,888,8888,9,99,999,9999}; ll a[maxn]; bool ac1(int n) { } int main() { int t; cin>>t; while(t--) { int n; cin>>n; int ok=0; for(int i=1;i<=n;i++) { cin>>a[i]; } for(int i=2;i<=n;i++) { if(a[i]!=a[i-1]) { ok=1;break; } } if(!ok) cout<<"NO"<<endl; else { int id; for(int i=1;i<n;i++) { if(a[i]!=a[i+1]) { id=i; break; } } int idl=id,idr=id+1; cout<<"YES"<<endl; for(int i=1;i<=n;i++) { if(i==idl) continue; if(a[i]!=a[idl]) { cout<<i<<" "<<idl<<endl; } else if(a[i]!=a[idr]) { cout<<i<<" "<<idr<<endl; } } } } }
E:http://codeforces.com/contest/1433/problem/E
題意:
n個人,n為偶數
分成兩組,每組圍成一個圈跳舞,問一共有多少種組合方式。
注意:1,2 3,4 和 3,4 1,2是同樣的分組方式
1,2,3,4和2,3,4,1是同一種跳舞排列方式。
解析:
首先,n個人中選兩個,有C(n,n/2)種,/2即為分組種類數。
分完組,接下來看圈:
先把跳舞人看成線性,那麼對於1,2,3,4 | 2, 3, 4, 1| 3, 4, 1, 2 。只要每個人的相對位置不變,那麼這個1不管在什麼位置,都是同一種排列方式。
所以對於一種排列方式,需要固定一個參照點,這個點不要動,其他的隨意放即可。
對於一個圈,n/2個人,先固定一個參照點,那麼還剩n/2-1個人,所以有(n/2-1)! 種排列方式,而另一個圈還有 (n/2-1)! 種
所以總的答案就是:C(n,n/2) * (n/2-1)! (n/2-1)! / 2
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e5 + 95; const int inf=999999999; int main() { ll n; cin>>n; ll sum=1; ll md=n; for(int i=1;i<=n/2;i++) { sum*=md; md--; } md=1; for(int i=1;i<=n/2;i++) { md*=i; } sum=sum/md; md=1; for(int i=1;i<=n/2-1;i++) { md*=i; } cout<<sum*md*md/2<<endl; }