2017-10-4 清北刷题冲刺班a.m

P101
zhx


a


【问题描述】
你是能看到第一题的 friends 呢。
——hja
Hja 拥有一套时光穿梭技术,能把字符串以超越光速的速度传播,但是唯一
的问题是可能会 GG。在传输的过程中,可能有四种情况:
1、字符串没有发生改变。
2、字符串的某一位由 0 变 1 或者由 1 变 0。
3、某一位消失了。
4、多了一位。
为了防止字符串 GG,Hja 保证发送的字符串只由 01 组成,并且所有字符
串开始的长度均为?,并且所有为 1 的位置的下标之和一定是? + 1的倍数。在
给定了你这些条件之后,Hja 告诉你传输之后的字符串,并按照以下规则复原
字符串:
1、对于一个字符串,按照四种规则从前到后的优先级依次尝试能否复原为
一个合法的字符串。
2、对于同一种操作,更靠前的位置更加优先。
3、对于同一种操作的同一位置,0 比 1 更加优先。
4、如果没有任何一种方法复原字符串,则输出−1。
【输入格式】
第一行一个整数?,代表所有字符串的长度。
接下来若干行,每行一个字符串。
【输出格式】
对于每个字符串,输出一行代表答案。
【样例输入】
4
0000
011
1011
11011
【样例输出】
0000
0110
1001
1111
【数据范围与规定】
对于100%的数据,4 ≤ ? ≤ 1000,字符串数量不超过3000。

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100000
using namespace std;
int mod,pos[maxn],cnt,del[maxn],w[maxn],sum[maxn];
string s;
bool f;
int n,len,l;
void dfs(int len,int Sum,int t){
    if(f)return;
    if(len==n&&Sum%mod==0){
        for(int i=0;i<l;i++){
            if(del[i])continue;
            printf("%c",s[i]);
        }
        printf("
");
        f=1;
        return;
    }if(t)return;
    if(len==n)return;
    for(int i=0;i<l;i++){
        if(!del[i]){
            del[i]=1;
            if(s[i]=='0'){
                dfs(len-1,Sum-w[i],1);if(f)return;
            }
            if(s[i]=='1'){
                dfs(len-1,Sum-(i+1)-w[i+1],1);if(f)return;
            }
            del[i]=0;
        }
    }
}
void dfs1(int c,int Sum,int t){
    if(f)return;
    
    if(Sum%mod==0){
        cout<<s<<endl;
        f=1;
        return;
    }if(t)return;
    if(c==0)return;
    for(int i=1;i<=cnt;i++){
        if(!del[pos[i]-1]){
            del[pos[i]-1]=1;
            s[pos[i]-1]='0';
            dfs1(c-1,Sum-pos[i],1);
            del[pos[i]-1]=0;
            s[pos[i]-1]='1';
        }
    }
    
}
int main(){
    //freopen("Cola.txt","r",stdin);
    freopen("a.in","r",stdin);freopen("a.out","w",stdout);
    scanf("%d",&n);
    mod=n+1;
    while(cin>>s){
        memset(del,0,sizeof(del));
        memset(w,0,sizeof(w));
        f=0;
        cnt=0;
        l=len=s.length();
        int Sum=0;
        for(int i=0;i<len;i++)
            if(s[i]=='1'){
                pos[++cnt]=i+1;
                Sum+=i+1;
            }
        for(int i=l-1;i>=0;i--){
            if(s[i]=='1')w[i]=w[i+1]+1;
            else w[i]=w[i+1];
        }
        if(len==n){//一定是1,2操作 
            if(Sum%mod==0){
                cout<<s<<endl;
                continue;
            }
            bool flag=0;
            dfs1(cnt,Sum,0);
            if(!f) printf("-1
");
            continue;
        }
        if(len>n){//删掉几位 
            if(len-n>1){
                printf("-1
");
                continue;
            }
            f=0;
            dfs(len,Sum,0);
            if(!f)printf("-1
");
            continue;
        }
        if(len<n){//加上几位 
            if(n-len>1){
                printf("-1
");
                continue;
            }
            int num=0;
            for(int i=len-1;i>=0;i--){
                if(s[i]=='1')    num+=i+1;
                sum[i]=sum[i+1]+(s[i]=='1'?1:0);
            }
            int ans=num%(n+1),flag=0;
            for(int i=0;i<=len;i++){
                if((sum[i]+ans)%(n+1)==0){
                    for(int j=0;j<len;j++)
                        if(j!=i)    cout<<s[j];
                        else if(i!=len)    cout<<"0"<<s[j];
                    if(i==len)    cout<<"0";
                    flag=1;
                    break;
                }
                if((sum[i]+ans+i+1)%(n+1)==0){
                    for(int j=0;j<len;j++)
                        if(j!=i)    cout<<s[j];
                        else if(i!=len)    cout<<"1"<<s[j];
                    if(i==len)    cout<<"1";
                    flag=1;
                    break;
                }
            }
            if(!flag)    cout<<"-1";
            printf("
");
        }
    }
    fclose(stdin);fclose(stdout);
    return 0;
}
100分 模拟

b


【问题描述】
你是能看到第二题的 friends 呢。
——laekov
Hja 和 Yjq 在玩游戏,这个游戏中 Hja 给了 Yjq 两个数?,?,希望 Yjq 找到
一些非负整数使得这些数的和等于?,并且所有数模?的值互不相同,求方案
数。
【输入格式】
一行两个整数?,?。
【输出格式】
一行一个整数代表答案对905229641取模之后的结果。
【样例输入 1】
3 3
【样例输出 1】
9
【样例输入 2】
523 44
【样例输出 2】
338398304
【数据范围与规定】
220,? ≤ 5。
4300,? ≤ 10。
70%的数据,? ≤ 10 18 ,? ≤ 20。
对于100%的数据,? ≤ 10 18 ,? ≤ 100。

#include<iostream>
#include<cstdio>
#define mod 905229641
using namespace std;
long long n,limit,sm[500010];
int m,ans;
void dfs(int yu,long long res,int use){
    if(res==0){
        ans=(ans+sm[use])%mod;
        return;
    }
    if(yu==m)return;
    if(res<0)return;
    dfs(yu+1,res,use);
    for(int i=0;i<=limit;i++)
        dfs(yu+1,res-(i*m+yu),use+1);
}
int main(){
    //freopen("Cola.txt","r",stdin);
    freopen("b.in","r",stdin);freopen("b.out","w",stdout);
    sm[1]=1;
    for(int i=2;i<=500000;i++)sm[i]=sm[i-1]*i%mod;
    cin>>n>>m;
    limit=n/m;
    dfs(0,n,0);
    printf("%d",ans);
    fclose(stdin);fclose(stdout);
    return 0;
}
20分 暴力
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

#ifdef unix
#define LL "%lld"
#else
#define LL "%I64d"
#endif

const int maxn=110;
const int maxs=maxn*maxn/2;
const int mo=905229641;

long long n;

int m,f[maxn][maxs],fac[maxn];

int calc(long long a,long long b)
{
    long long ans=1;
    for (int c=1;c<a;c++)
        ans=ans*(b+c)%mo;
    return (int)ans;
}

int main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);

    scanf(LL "%d",&n,&m);
    f[0][0]=1;
    int up=m*(m-1)/2;
    for (int a=0;a<m;a++)
        for (int b=m;b>=0;b--)
            for (int c=up;c>=0;c--)
                if (f[b][c]) f[b+1][c+a]=(f[b+1][c+a]+f[b][c])%mo;
    fac[0]=1;
    for (int a=1;a<=m;a++)
        fac[a]=(long long)fac[a-1]*a%mo;
    int x=(int)(n%m);
    int ans=0;
    for (int a=x;a<=n && a<=up;a+=m)
    {
        long long rest=(n-a)/m;
        for (int b=1;b<=m;b++)
            if (f[b][a])
            {
                int nowans=calc(b,rest%mo);
                nowans=(long long)nowans*f[b][a]%mo;
                nowans=(long long)nowans*b%mo;
                ans=(ans+nowans)%mo;
            }
    }
    printf("%d
",ans);

    return 0;
}
100分

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
【数据规模与约定】
30%的数据,1 ≤ ?,? ≤ 100。
对于100%的数据,1 ≤ ?,? ≤ 100000。

#include<iostream>
#include<cstdio>
#define maxn 100010
using namespace std;
int n,m,w[maxn],ans=0,a[maxn*2],cnt;
struct node{
    int l,r,v;
}p[maxn];
void dfs(int now,int sum){
    if(now==m+1){
        ans=max(ans,sum);
        return;
    }
    dfs(now+1,sum);
    int due=0;
    int pos=cnt+1;
    for(int i=p[now].l;i<=p[now].r;i++)due+=w[i],a[++cnt]=w[i],w[i]=0;
    dfs(now+1,sum-due+p[now].v);
    for(int i=p[now].l,j=pos;i<=p[now].r;i++,j++)w[i]=a[j];
    cnt=pos-1;
}
int main(){
    //freopen("Cola.txt","r",stdin);
    freopen("c.in","r",stdin);freopen("c.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].v);
    dfs(1,0);
    cout<<ans;
    fclose(stdin);fclose(stdout);
    return 0;
}
10分 暴力
#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 "
", ans);
}
100分
原文地址:https://www.cnblogs.com/thmyl/p/7625379.html