Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!(A~D)

A. Johnny and Ancient Computer(因子拆分)

分析

  • 題意
  1. 給我們兩個數a、b,現在我們我們可以對 a來了進行一些系列的x2 、x4、 x8、 /2 、/4、 /8 等運算操作,問我們通過一些這樣的操作以後能否把a變成b,如果能輸出需要的最小次數,否則輸出-1
  • 分析
  1. 這個題中既可能有乘法 又有 除法操作,我們可能 在輸入a、b的之後,如果 a < b的話,我們交換二者的值,令a始終保持較大值,這樣我們只需要對a進行 除法操作了,如果 對a進行 /2 /4 /8的操作之後要想得到最終結果 a == b ,那我們可以令c = a / b(這裏要確保 a % b == 0),這樣我們依次從c中拆分出儘可能多的 8、在拆分儘可能多的4、最後拆分出儘可能對2 ,這樣拆分完之後如果剩下的數不是1的話,直接輸出-1,否則的話答案就是拆分出 8,4,2的總共數量

代碼

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

int br[10];
int ar[5];

int main()
{
    /* fre(); */
    int T;
    scanf("%d\n", &T);
    ar[1] = 8, ar[2] = 4, ar[3] = 2;
    while(T --)
    {
        ll a, b;
        scanf("%lld %lld", &a, &b);
        if(a < b) swap(a, b);
        if(a % b)
        {
            printf("-1\n");
            continue;
        }

        ll c = a / b;
        memset(br, 0, sizeof(br));
        for(int i = 1; i <= 3; i ++)
        {
            while(c % ar[i] == 0)
            {
                c /= ar[i];
                br[ar[i]] ++;
            }
        }
        if(c != 1)
        {
            printf("-1\n");
            continue;
        }
        printf("%d\n", br[2] + br[4] + br[8]);
    }

    return 0;
}

B. Johnny and His Hobbies(暴力)

分析

  • 題意
  1. 給我們s個數讓我們照出一個最小正整數k,是s個數都 異或k 得到的值形成一個集合a,要求a與s中所包含的元素完全相同,求這個k
  • 分析
  1. 由於數據範圍比較小,我們直接暴力求解k的最合適值

代碼

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 1e3 + 100;
int ar[mxn];
int br[mxn];
int cr[mxn];

int main()
{
    /* fre(); */
    int T;
    scanf("%d\n", &T);
    while(T --)
    {
        memset(br, 0, sizeof(br));
        int n;
        scanf("%d\n", &n);
        for(int i = 1; i <=n; i ++)
            scanf("%d", &ar[i]), br[ar[i]] = 1;
        int ans = 0;
        for(int i = 1; i <= 1024; i ++)
        {
            memset(cr, 0, sizeof(cr));
            int fg = 1;
            for(int j = 1; j <= n; j ++)
            {
                int t = (ar[j] ^ i);
                if(++ cr[t] >= 2)
                {
                    fg = 0;
                    break;
                }
            }
            if(fg == 0)
                continue;

            for(int j = 0; j <= 1024; j ++)
            {
                if(br[j] != cr[j])
                {
                    fg = 0;
                    break;
                }
            }
            if(fg)
            {
                ans = i;
                break;
            }
        }

        if(ans == 0)
            printf("-1\n");
        else
            printf("%d\n", ans);
    }

    return 0;
}

C. Johnny and Another Rating Drop

分析

  • 分析

000
001
010
011
100
101

  1. 因爲二進制是逢二進一,所以我們依次觀察二進制的最地位到高位發現,
  2. 對於 二進制值倒數第1位,這一位對答案的貢獻是 n
  3. 對與 二進制的倒數第2位,這一位對答案的貢獻是 n / 2
  4. 對於 二進制的倒數第3位,這一位對答案的貢獻是 n / 4
  5. 綜上 二進制的倒數第i位,對答案的貢獻是 n/2i1n/2^{i-1},
  6. 所以 答案 ans = n/1 + n/2 + n/4 …
  • 還有一種方法也是規律,規律是:2*n - 二進制中1的數量 =ans,,,這個規律爲什麼對,我也無法解釋,但 確實ac了

代碼一

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353
const int mxn = 1e6 + 100;

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        ll n, i = 1, ans = 0;
        scanf("%lld\n", &n);
        ll now = n;
        while(now)
        {
            ans += n / i;
            i *= 2;
            now >>= 1;      
        }
        printf("%lld\n", ans);
    }



    return 0;
}

代碼二

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353

const int mxn = 1e3 + 100;

int main()
{
    /* fre(); */
    int T;
    scanf("%d\n", &T);
    while(T --)
    {
        ll n, t;
        scanf("%lld", &n);
        t = n;
        ll ct = 0;
        while(n)
        {
            if(n & 1) ct ++;
            n >>= 1;
        }
        printf("%lld\n", t * 2 - ct);
    }

    return 0;
}

D. Johnny and Contribution(模擬+貪心)

分析

  • 題意
  1. 給我們一個有n個節點m邊的無向圖,每個節點有一個 1~n的目標權值,然後我們對每個節點進行染色(給這個節點賦上一個 1~n的權值),對於某個節點我要染色的規則是,與當前節點相鄰的節點中沒有出現過的顏色(權值數字)中最小的那個權值數字我賦值給當前的 節點,通過這樣的染色操作之後,如果每個節點的新權值與 目標權值都先相同的話,輸出染色節點的順序,否則輸出-1
  • 分析
  1. 貪心,易得我們應該按照期望從小到大塗色,首先我們包期望爲1的節點u都塗掉,然後判斷與其直接相連的節點v 如果如果它的期望也爲1,我們就把v的期望顏色++,
  2. 以此類推,因爲是從小開始塗顏色的,所以保證比當前u顏色小的節點都塗過顏色了,接着我就直接判斷,只要當前節點u的期望不是原來的顏色,我們就可以直接返回-1,最後 注意一下初始化期望顏色爲1

代碼

#include <bits/stdc++.h>
using namespace std;
void fre() { freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long 
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define INF 0x3f3f3f3f
#define mod 998244353
const int mxn = 1e6 + 100;

vector<int> e[mxn];
vector<int> col[mxn];
vector<int> ans;
int num[mxn];

int main()
{
    /* fre(); */
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 1, u, v; i <= m; i ++)
    {
        scanf("%d %d", &u, &v);
        e[u].pb(v);
        e[v].pb(u);
    }
    for(int i = 1, t; i <= n; i ++)
    {
        scanf("%d", &t);
        col[t].pb(i);
        num[i] = 1;             //初始的時候,每個節點周圍只有一個 自己1個節點
    }

    for(int i = 1; i <= n; i ++)
    {
        for(auto u : col[i])
        {
            if(num[u] != i) printf("-1\n"), exit(0);
            for(auto v : e[u])
                if(num[v] == i) num[v] ++;
            ans.pb(u);
        }
    }

    for(auto i : ans) printf("%d ", i);

    return 0;
}

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