1. 程式人生 > 實用技巧 >Codeforces Round #677 (Div. 3)(A->E(排列組合))

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;
}