1. 程式人生 > >國慶清北刷題衝刺班 Day4 上午

國慶清北刷題衝刺班 Day4 上午

a

【問題描述】
你是能看到第一題的friends呢。
——hja

Hja擁有一套時光穿梭技術,能把字串以超越光速的速度傳播,但是唯一的問題是可能會GG。在傳輸的過程中,可能有四種情況:
1、 字串沒有發生改變。
2、 字串的某一位由0變1或者由1變0。
3、 某一位消失了。
4、 多了一位。
為了防止字串GG,Hja保證傳送的字串只由01組成,並且所有字串開始的長度均為 ,並且所有為1的位置的下標之和一定是 的倍數。在給定了你這些條件之後,Hja告訴你傳輸之後的字串,並按照以下規則復原字串:
1、 對於一個字串,按照四種規則從前到後的優先順序依次嘗試能否復原為一個合法的字串。
2、 對於同一種操作,更靠前的位置更加優先。
3、 對於同一種操作的同一位置,0比1更加優先。
4、 如果沒有任何一種方法復原字串,則輸出 。
【輸入格式】
第一行一個整數 ,代表所有字串的長度。
接下來若干行,每行一個字串。
【輸出格式】
對於每個字串,輸出一行代表答案。
【樣例輸入】
4
0000
011
1011
11011
【樣例輸出】
0000
0110
1001
1111
【資料範圍與規定】
對於 的資料, ,字串數量不超過 。

略噁心的模擬, 考場爆零,直接GG

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 2005
int n,num[MAXN];
char s[MAXN];

bool check1(char *s){
    int len = strlen(s+1);
    if(len != n) return false;
    int Sum = 0;
    for(int i=1
; i<=n; ++i) if(s[i] == '1') Sum += i; for(int i=1; i<=n; ++i) if(s[i] == '1'){ Sum -= i; if(Sum % (n+1) == 0){ s[i] = '0'; printf("%s\n",s+1); return true; } Sum += i; } return
false; } bool check4(char *s){ int len = strlen(s+1); if(len != n) return false; int Sum = 0; for(int i=1; i<=len; ++i) if(s[i] == '1') Sum += i; if(Sum % (n+1) == 0){ printf("%s\n",s+1); return true; } return false; } bool check3(char *s){//多了一位 ---- > 消掉 int len = strlen(s+1); if(len != n+1) return false; int Sum = 0; for(int i=1; i<=len; ++i) { num[i] = num[i-1]; if(s[i] == '1') Sum += i,++num[i]; } for(int i=1; i<=len; ++i){ Sum -= num[len] - num[i]; if(s[i] == '1') Sum -= i; if(Sum % (n+1) == 0){ for(int j=1; j<i; ++j) printf("%c",s[j]); for(int j=i+1; j<=len; ++j) printf("%c",s[j]); printf("\n"); return true; } Sum += num[len] - num[i]; if(s[i] == '1') Sum += i; } return false; } bool check2(char *s){ int len = strlen (s+1); if(len != n-1) return false; int Sum = 0; for(int i=1; i<=len; ++i){ num[i] = num[i-1]; if(s[i] == '1') Sum += i,++num[i]; } for(int i=1; i<=n; ++i){ Sum += num[len] - num[i-1]; if(Sum % (n+1) == 0){ for(int j=1; j<i; ++j) printf("%c",s[j]); printf("0"); for(int j=i; j<=len; ++j) printf("%c",s[j]); printf("\n"); return true; } Sum += i; if(Sum % (n+1) == 0){ for(int j=1; j<i; ++j) printf("%c",s[j]); printf("1"); for(int j=i; j<=len; ++j) printf("%c",s[j]); printf("\n"); return true; } Sum -= i + num[len] - num[i-1]; } return false; } int main(int argc,char *argv[]){ freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d",&n); while(~scanf("%s",s+1)){ bool ok = false; ok = check4(s); if(ok) continue; ok = check1(s); if(ok) continue; ok = check2(s); if(ok) continue; ok = check3(s); if(ok) continue; printf("-1\n"); } fclose(stdin);fclose(stdout); return 0; }

b

【問題描述】
你是能看到第二題的friends呢。
——laekov

Hja和Yjq在玩遊戲,這個遊戲中Hja給了Yjq兩個數 ,希望Yjq找到一些非負整數使得這些數的和等於 ,並且所有數模 的值互不相同,求方案數。
【輸入格式】
一行兩個整數 。
【輸出格式】
一行一個整數代表答案對 取模之後的結果。
【樣例輸入1】
3 3
【樣例輸出1】
9
【樣例輸入2】
523 44
【樣例輸出2】
338398304
【資料範圍與規定】
對於 的資料, 。
對於 的資料, 。
對於 的資料, 。
對於 的資料, 。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>

using namespace std;
#define LL long long
#define Mod 905229641
#define MAXN 110
LL n,m,f[MAXN][MAXN * MAXN],fac[MAXN];

void Prepare(){
    f[0][0] = 1;
    for(int i=0; i<=m-1; ++i)
        for(int j=i; j>=0; --j)
            for(int k=0; k<=m*(m-1)/2-i; ++k)
                if(f[j][k]) f[j+1][k+i] = (f[j][k] + f[j+1][k+i]) % Mod;
    fac[1] = 1;
    for(int i=2; i<=m; ++i) fac[i] = fac[i-1] * i % Mod;
}

LL Fast_Pow(LL x,int b){
    LL ret = 1;
    while(b){
        if(b & 1) ret = (ret * x) % Mod;
        x = (x * x) % Mod,b >>= 1;
    }
    return ret;
}

int main(int argc,char *argv[]){
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    scanf("%I64d%I64d",&n,&m);
    Prepare();
    LL Ans = 0;
    for(int i=0; i<=m*(m-1)/2; ++i)
        if((n-i) % m == 0){
            LL x = ((n - i) / m) % Mod;
            LL tot = 1;
            for(int j=1; j<=m; ++j){
                Ans = (Ans + f[j][i] * fac[j] % Mod * tot % Mod) % Mod;
                tot = (tot * (x + j) % Mod * Fast_Pow(j,Mod-2) % Mod) % Mod;
            }
        }
    printf("%I64d\n",Ans);
    fclose(stdin); fclose(stdout);
    return 0;
}

c

【問題描述】
你是能看到第三題的friends呢。
——aoao

Hja回到老家開始種地,由於太久沒有種地,所以所有地都是荒地。將每片地從荒地變成不荒地有一定的代價,但是一旦改變之後就不再是荒地了。現在Hja要開始 年的種地生活,第 年Hja可以在 到 塊地上種地,並且可以獲得 的收益。(注意,要種地必須整段一起種,並且這些地一定已經是不荒地)Hja可以選擇種或者不種每一年的地,問Hja能夠獲得的最大收益。
【輸入格式】
第一行兩個整數 ,代表地的數量和年數。
接下來一行 個數,代表每塊地變成不荒地的代價。
接下來 行,每行三個整數 如題意描述。
【輸出格式】
一行一個整數代表答案。
【樣例輸入】
7 4
3 2 3 2 1 2 3
1 2 5
2 3 5
3 5 3
7 7 5
【樣例輸出】
4
【資料規模與約定】
對於 的資料, 。
對於 的資料, 。

線段樹優化DP,種地時間其實對本題並沒有任何影響

//附上 zhx 的程式碼
#include <cstdio>
#include <cctype>
#include <memory.h>
#include <algorithm>

using namespace std;

typedef long long qw;

#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif

int nextInt() {
    int s = 0, d;
    bool nag = 0;
    do {
        d = getchar();
        if (d == '-')
            nag = 1;
    } while (!isdigit(d));
    do
        s = s * 10 + d - 48, d = getchar();
    while (isdigit(d));
    return nag ? -s : s;
}

struct seg {
    int l, r;
    qw v, z;
    seg *ls, *rs;
};
struct obj {
    int l, r, v;
};

inline bool cmpObj(const obj& a, const obj& b) {
    return (a. l < b. l) || (a. l == b. l && a. r < b. r);
}

const int maxn = 200009;
const qw inf = 0x3f3f3f3f3f3f3f3fLL;

int n, m;
obj q[maxn];
qw s[maxn], ans;
seg *rtf, *rtc, *sp;

#define mid(p) ((p->l+p->r)>>1)

seg *sgtBuild(int l, int r) {
    seg *p = sp ++;
    p-> v = - inf;
    p-> z = 0;
    p-> l = l;
    p-> r = r;
    if (l + 1 < r) {
        p-> ls = sgtBuild(l, mid(p));
        p-> rs = sgtBuild(mid(p), r);
    }
    return p;
}

void sgtChg(seg* p, int p0, qw v0) {
    if (p-> l + 1 == p-> r)
        p-> v = max(p-> v, v0);
    else {
        if (p0 < mid(p))
            sgtChg(p-> ls, p0, v0 - p-> z);
        else
            sgtChg(p-> rs, p0, v0 - p-> z);
        p-> v = max(p-> ls-> v, p-> rs-> v) + p-> z;
    }
}

qw sgtQry(seg* p, int l, int r) {
    if (l >= r)
        return -inf;
    else if (p-> l == l && p-> r == r)
        return p-> v;
    else if (r <= mid(p))
        return sgtQry(p-> ls, l, r) + p-> z;
    else if (l >= mid(p))
        return sgtQry(p-> rs, l, r) + p-> z;
    else
        return max(sgtQry(p-> ls, l, mid(p)), sgtQry(p-> rs, mid(p), r)) + p-> z;
}

void sgtLazy(seg* p, int l, qw z0) {
    if (p-> v == -inf)
        return;
    else if (p-> l == l)
        p-> v += z0, p-> z += z0;
    else {
        if (l < mid(p)) {
            sgtLazy(p-> ls, l, z0);
            sgtLazy(p-> rs, mid(p), z0);
        }
        else
            sgtLazy(p-> rs, l, z0);
        p-> v = max(p-> ls-> v, p-> rs-> v) + p-> z;
    }
}

int main() {
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    sp = new seg[maxn * 6];
    n = nextInt();
    m = nextInt();
    rtf = sgtBuild(0, n + 2);
    rtc = sgtBuild(0, n + 2);
    s[0] = 0;
    for (int i = 1; i <= n; i ++)
        s[i] = s[i - 1] + nextInt();
    for (int i = 0; i < m; i ++) {
        q[i]. l = nextInt();
        q[i]. r = nextInt();
        q[i]. v = nextInt();
    }
    sort(q, q + m, cmpObj);
    ans = 0;
    for (int i = 0; i < m; i ++) {
        qw res0 = max(sgtQry(rtf, 0, q[i]. l), 0LL) - s[q[i]. r] + s[q[i]. l - 1];
        qw res1 = sgtQry(rtc, q[i]. l, q[i]. r + 1) - s[q[i]. r];
        qw res = max(max(res0, res1), sgtQry(rtf, q[i]. r, n + 1)) + q[i]. v;
        sgtLazy(rtf, q[i]. r, q[i]. v);
        sgtLazy(rtc, q[i]. r, q[i]. v);
        sgtChg(rtf, q[i]. r, res);
        sgtChg(rtc, q[i]. r, res + s[q[i]. r]);
        ans = max(ans, res);
    }
    printf(lld "\n", ans);
}