Educational Codeforces Round 88 (Rated for Div. 2)(A~D)

A. Berland Poker(簡單情況討論)

分析

  • 思路
  1. 主要的思路就是,先計算出平均每個手中手中的牌的數量ct,這個時候我們考慮,接下來要先讓分數儘可能的大,就應該讓 儘可能多的的joker牌在一個人的手中,那麼我們就分類討論
  2. 如果m<=ctl,就把m張牌都給一個人
  3. 如果m>ct,就把ct張牌給一個人,然後剩下的牌 平均分配就行了

代碼

#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 = 2e5 + 10;
int ar[mxn];

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n, m, k;
        scanf("%d %d %d", &n, &m, &k);
        int ct = n / k;
        int mx = min(ct, m);
        int sr = m - mx;
        k --;
        int ans = mx - ceil((db)sr / k);
        printf("%d\n", ans);
    }

    return 0;
}

B. New Theatre Square(模擬)

分析

  • 題意
  1. 給我們一個n*m的方格區域,這個放個區域內 , *表示已經鋪過磚了,而’.'表示還沒有鋪過磚,
  2. 現在給我們兩種規格:1x1的磚、1x2的磚,花費的代價對應爲 a、b,注意這兩種磚只能 橫向鋪方格區域,不能豎着鋪
  3. 問將方格中的 空白區域鋪滿最少需要的代價是多少?
  • 思路
  1. 首先我們對於1x2的磚話費的最少代價爲 b = min(b, 2*a),
  2. 之後就是在某一行中,如果某個 連續空白格的數量是偶數的話,我們全部用1X2的磚去鋪,否則用一個1x1的磚之後剩下的都用2x2的磚去鋪
  3. 模擬遍歷一遍,統計總費用

代碼

#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 + 10;
char ar[mxn][mxn];

int main()
{
    /* fre(); */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n, m, a, b;
        scanf("%d %d %d %d", &n, &m, &a, &b);
        b = min(2 * a, b);
        for(int i = 1; i <= n; i ++)
        {
            scanf("%s", ar[i] + 1);
            ar[i][0] = '*';
            ar[i][m + 1] = '*';
        }

        int sum = 0;
        for(int i = 1; i <= n; i ++)
        {
            int lst = m;
            int pre = m;
            for( ; pre >= 0; pre -- )
            {
                if(ar[i][pre] == '*')
                {
                    sum += (lst - pre) / 2 * b + (lst - pre) % 2 * a;
                    lst = pre - 1;
                }

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

    }

    return 0;
}


C. Mixing Water(二分/三分/數學 )

分析

  • 題意
  1. 給我們一個空桶,我們可以向其中 倒入 x杯熱水,之後可以選擇向其中倒入 (x-1)或者 x 杯涼水 , 熱水的溫度爲 h,冷水的溫度爲c,
  2. 倒入桶中的溫度爲水的平均溫度
  • 思路
  1. 這一題並不難,可惜當時題意讀錯了,這裏說一下三分的做法
  2. 我們先討論如果 h+c>=2*t的話,那麼我們就只需要 1杯熱水和1杯涼水
  3. 否則的話,我們就一定需要x+1杯熱水,x杯涼水,但是x的具體值我們不知道,但是我們大致知道,隨着x的增加應該是一個 拋物線形狀的變化曲線,所以我們可以用三分去枚舉x,

代碼

#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

ll h, c, t;
db check(db a, db b)
{
    return abs((a * h + b * c) / (a + b) - t);
}


int main()
{
    /* fre(); */
    int T; 
    scanf("%d", &T);
    while(T --)
    {
        scanf("%lld %lld %lld", &h, &c, &t);

        if(h + c >= 2 * t)
        {
            printf("2\n");
        }
        else
        {
            ll l = 0, r = INF, lm, rm;
            while(l < r)
            {
                lm = l + (r - l) / 3;
                rm = r - (r - l) / 3;

                if(check(lm + 1, lm) <= check(rm + 1, rm))
                    r = rm - 1;
                else
                    l = lm + 1;
            }
            printf("%lld\n", 2 * l  + 1LL);
        }
    }

    return 0;
}

D. Yet Another Yet Another Task(思維+方法)

分析

  • 題意
  1. 給我們一個序列ar[i],讓我們在這個序列中選擇連續的一個區間,我們得到分數=這個區間中所有的元素和 - 這個區間中元素的最大值,問通過可以的選擇區間我們能夠得到的最大的分數是多少?
  • 思路
  1. 注意到序列元素的值在 [30,30][-30,30]之間,這肯定是有用的一點,
  2. 而我們主要思路就是通過枚舉區間元素的最大值x,這樣一旦 在遍歷數組的時候遇到ar[i]>x,那麼當前的區間端就要從i這個位置斷開,之後從i+1位置開始下一個連續區間的,
  3. 其次是我們在遍歷尋找符合題意的區間段的時候,我們要在每一個位置都要維護區間最大和 即:ans=max(ans,sum)ans=max(ans,sum)

代碼

#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 = 1e5 + 100;
int ar[mxn];

int main()
{
    /* fre(); */
    int n;
    scanf("%d\n", &n);
    for(int i = 1; i <= n; i ++)
        scanf("%d\n", &ar[i]);
    int ans = 0;
    for(int i = 1; i <= 30; i ++)
    {
        int sum = 0;
        for(int j = 1; j <= n; j ++)
        {
            if(ar[j] > i)
                sum = 0;
            else
            {
                sum += ar[j];
                if(sum < 0) sum = 0;
                ans = max(ans, sum - i);
            }
        }
    }
    printf("%d\n", ans);

    return 0;
}


E. Modular Stability(數論)

分析

  • 題意
  1. 給我們一個由n個數組成序列S={1,2,3…n},現在我們 我可以從中任意選擇k個數按從小到大的順序組成一個新的序列ar,
  2. 如果存在正整數x令: x%ar[1]%ar[2]...%ar[k]==~x\%ar[1]\%ar[2]...\%ar[k]== x按任意順序區域ar中的元素之後的值,則ar爲穩定數組
  3. 問有多少選擇方案,使產生的 ar 爲穩定數組
  • 思路
  1. 易得上式的取值結果,有ar中最小的值決定,我設這個最小值爲ar1
  2. 我們設x=nar1+mx=n*ar1+m,那麼m就是表達式最終的取餘的結果,接着我們推出 (n1a1+m)%ar[i]=(n2ar1+m)(n1 * a1+m)\%ar[i]=(n2*ar1+m),我可以得出ar中任意一個數都要是ar1的倍數,這個樣就能保證任意的取餘順序都能保證得到的取餘結果相同了,
  3. 又因爲ar中元素各不相同,所以我們只要枚舉 ar1的值,剩下的就是在n/ar[i]-1個ar1的倍數中 選擇k個就行了,最終總方案數就是i=1nCn/i1k1\sum_{i=1}^nC_{n/i-1}^{k-1}.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章