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

Posted Soda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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("\n");
        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\n");
            continue;
        }
        if(len>n){//删掉几位 
            if(len-n>1){
                printf("-1\n");
                continue;
            }
            f=0;
            dfs(len,Sum,0);
            if(!f)printf("-1\n");
            continue;
        }
        if(len<n){//加上几位 
            if(n-len>1){
                printf("-1\n");
                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("\n");
        }
    }
    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分 暴力

 

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分 暴力

 

以上是关于2017-10-4 清北刷题冲刺班a.m的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

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

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

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