Codeforces Round #653 (Div. 3)(A~E)

題目傳送門

A. Required Remainder

思路

  • 題意
  1. 給我們n,x,y 的值 讓我們找到 k%x==y的k最大值,0<=k<=n0<=k<=n
  • 分析
  1. 很水的一道題, 考慮n中包含x的數量爲ct=n/xct=n/x, 我們肯定要把這些包含x全部用上, 纔可以使k更大, 全部用上得到的k爲 ctk+yct*k+y,但是我們要 特殊考慮 如果ct*k+y >n的話要使 答案變成 ct * k + y - x

代碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
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 (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = s; i <= e; i ++)
using namespace std;

const int mxn = 2e5 + 10;
ll ar[mxn];

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int x, y, n;
        scanf("%d %d %d", &x, &y, &n);
        int t = n / x * x;
        int val = t + y;
        if(val > n)
            val -= x;
        printf("%d\n" ,val);
    }

    return 0;
}

B. Multiply by 2, divide by 6

思路

  • 題意
  1. 給我們一個數n,我們可以對其進行兩種操作:
    1. 令 n *= 2
    2. 兩 n /= 6(當 n%6==0的時候)
  2. 問最少經過多少次 操作 可以把 n 變成1 ?
  • 分析
  1. 首先我們想,如果n一直進行操作2.一直 n除以6的話,最後的結果得到一個1,這是最理想的,最少的操作次數,
  2. 我們可以把 讓n除6這個操作 看成讓n先除3,在除2, 那麼我們假設n最多可以除以 x個3, 假設 n最多可以除以y個2(求x,y的過程用 因數分解,把n按因子2、3分解 如果最後分解出來剩下的數不是1的話,輸出-1)
    1. 因爲n實際上除的是6=3*2,所以 n 可以除以x個3,就要求最多隻能被x個連續的2整除,所以如果y > x 的話,我們無論如何 都沒法消去多的2yx2^{y-x}次方, 所以輸入-1
    2. 而如果y < x 的話,我們可以通過 操作1 來增加n中包含2的數量,即:增加y的數量,令y與x 相等,此時x-y就是 要進行1操作的次數, 而x的數量就是 要進行操作2的次數, 兩次數想加就是ans

代碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
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 (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = s; i <= e; i ++)
#define rep_(i, e, s) for(int i = e; i >= s; i --)
using namespace std;

const int mxn = 2e5 + 10;
ll ar[mxn];
int br[5];

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        memset(br, 0, sizeof(br));
        int n;
        scanf("%d", &n);
        rep_(i, 3, 2)
        {
            while(n % i == 0)
            {
                br[i] ++;
                n /= i;
            }
        }

        if(n == 1)
        {
            if(br[3] < br[2])
                printf("-1\n");
            else
                printf("%d\n", br[3] - br[2] + br[3]);
        }
        else
            printf("-1\n");
    }


    return 0;
}


C. Move Brackets

思路

  • 分析
  1. 這題沒啥說的,就是 stack 的經典應用題,答案就是 最後還在站內的字符的數量 / 2

代碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
#include<stack>
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 (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = s; i <= e; i ++)
#define rep_(i, e, s) for(int i = e; i >= s; i --)
using namespace std;

const int mxn = 2e2 + 10;
char ar[mxn];

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n;
        scanf("%d", &n);
        scanf("%s", ar + 1);
        stack<char> st;
        for_(i, 1, n)
        {
           if(st.empty()) 
                st.push(ar[i]);
           else
           {
               if(st.top() == '(' && ar[i] == ')') 
                   st.pop();
               else
                   st.push(ar[i]);
           }
        }
        printf("%lu\n", st.size() / 2);
    }

    return 0;
}

D. Zero Remainder Array

思路

  • 題意
  1. 給我們一個一個長度爲n 的序列a,現在我們要通過下面兩種操作,使a中所有元素能夠被k整除, 又給我們的一個變量x(初始值爲0)

    1. a[i]+=x,x++a[i]+=x,x++,這個操作 對每個元素a[i]最多隻能使用一次
    2. x++x++
  2. 問我們 最少需要 多少次上面的操作?

  • 分析
  1. 在a中元素中如果已經可以被k整除的話,我們不需要對他們進行操作,我們假設剩下的不能被k整的除的元素的形成的新數組b,對於b中的元素我們求出的每個b中元素bib_i距離k某個倍數差了多少,這些差值形成一個新的數組c。
    1. 舉例:b :{1、1、4、 5} ,k = 3,對於b中每個元素bibi 減去 k 的某個倍數(這個倍數爲(bi/k+1)k(b_i/k+1)*k)
    2. 之後得到c:{ 2,2,2,1}–>即:c:{1,2,2,2},
    3. 對於c中第一個元素1,我們需要先把x從0變爲1(通過操作2),之後再通過一次 操作1 加到第一個元素1上,就是能使c中第一個數對應的在b中的元素可以被k整除了(之後x變爲了1+1=2)
    4. 接着考慮c中第一個元素2,我需要 2 - x次第一種的操作,和1次第二種的操作,總結一下就是需要(cix+1c_i-x+1次兩種操作,之後x=ci+1=2+1x=c_i+1=2+1),
    5. 接下來考慮c3=2c_3=2,這個時候我們發現x=3>2,兩種操作都沒有進行的意義了,這個時候我們只能無奈使c3c_3的值增大1*k(只要這樣纔可以付出,小的代價,而繼續操作),令c_3+= k == 5,這樣我們需要的進行的次數爲53+1=35-3+1=3之後x變成了6,
    6. 當我們進行第四個元素的時候,發現x=6>2,這個時候的我們讓 c4+=2kc_4+=2*k,這樣又可以進行操作了
  2. 核心的過程就是這樣,這個過程的中 特別注意的就是 對於c中重複的元素我們應該 不斷的讓重複的加上 不同的k的倍數 ,之後所有c中的元素就的各不相同了,我們就可以 for循環一遍求出 ans了

代碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
#include<stack>
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 (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = (s); i <= (e); i ++)
#define rep_(i, e, s) for(int i = (e); i >= (s); i --)
using namespace std;

const int mxn = 2e5 + 10;
vector<ll> v;
vector<ll> res;

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        v.clear();
        res.clear();
        ll n, k;
        scanf("%lld %lld", &n, &k);
        ll t;
        for_(i, 1, n)
        {
            scanf("%lld", &t);
            if(t % k)
            {
                ll ct = t / k;
                ll val = k * (ct + 1) - t;
                v.pb(val);
            }
        }

        sort(v.begin(), v.end());
        pair<ll, ll> p;
        p.fi = -1, p.se = 0;

        for(int i = 0; i < v.size(); i ++)
        {
            if(v[i] != p.fi)
            {
                res.pb(v[i]);
                p.fi = v[i];
                p.se = 1;
            }
            else
            {
                res.pb(v[i] + k * p.se);
                p.se ++;
            }
        }
        sort(res.begin(), res.end());
        ll sum = 0;
        ll x = 0;
        for(auto s : res)
        {
            sum += (s - x + 1);
            x = s + 1;
        }

        printf("%lld\n", sum);
    }

    return 0;
}


E1. Reading Books (easy version)

思路

  • 題意
  1. 給我們n本書,每本書有三個參數 t、a、b,分別爲:看這本書所需要的時間、a1表示 愛麗絲 喜歡這本書、b1表示 鮑勃 喜歡這本書
  2. 現在 他們兩個人都要從n本書中選擇k本喜歡的數,他們兩個人選擇的書 形成一個共享的集合(就是兩個人 選擇選擇的書的種類的並集 ),最閱讀的總時間爲這個集合的 沒種書閱讀時間tit_i想加,
  3. 求這個最小時間,如果兩個人都選擇出k本喜歡的書,輸出-1
  • 分析
  1. 這一題根據貪心,首先兩個人選擇的書的總種類越少越好,而且兩個都應該只選k本喜歡的書,不能多選,
  2. 此外我們可以把:兩本書(一本愛麗絲喜歡,另一本鮑勃喜歡,而且選擇的這兩本書的時間之和儘量小)看做一本新的書,這樣 這本 新讀書 閱讀的總時間就要 原來的兩本書的時間之和,,,這樣我們不斷的選擇兩本書,儘可能的多拼湊出新的書,這本新書兩個人都喜歡
  3. 這樣,我們 把所有 『拼湊出的書』和 所有原來 就已經被兩個人同時喜歡的書 放在一起形成一個集合 S,從S中選擇k本時間最短的書就是ans(當然如果S中書的數量<k 那麼就是無解,輸出-1)

代碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<string>
#include<cstdio>
#include<cmath>
#include<stack>
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 (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = (s); i <= (e); i ++)
#define rep_(i, e, s) for(int i = (e); i >= (s); i --)
using namespace std;

const int mxn = 2e5 + 10;
queue<ll> q;
vector<ll> v;
int a[mxn];
int b[mxn];

int main()
{
    /* fre(); */
    ll n, k;
    scanf("%lld %lld", &n, &k);
    int t, x, y;
    int na = 0, nb = 0;
    for_(i, 1, n)
    {
        scanf("%d %d %d", &t, &x, &y);
        if(x == 1 && y == 1)
            v.pb(t);
        else if(x == 1 && y == 0)
            a[na ++] = t;
        else if(y == 1 && x == 0)
            b[nb ++] = t;
    }
    sort(a, a + na);
    sort(b, b + nb);
    /* for_(i, 0, na - 1) */
    /*     cout << a[i] << " "; */
    int ct = min(na, nb);
    for_(i, 0, ct - 1)
        v.pb(a[i] + b[i]);
    if(v.size() >= k)
    {
        sort(v.begin(), v.end());
        int sum = 0;
        for_(i, 0, k - 1)
            sum += v[i];
        printf("%d\n", sum);
    }
    else
    {
        printf("-1\n");
    }


    return 0;
}


剩下題的之後再補。。。。。。。。。。。。

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