• 2014-9-13 NOIP模拟赛


    NOIP2014模拟赛

    ——lwher

    题目名

    环上的游戏

    舞蹈课

    数位和乘积

    源文件

    cycle.cpp/c/pas

    dancingLessons.pas/cpp

    digit.cpp.cpp/c/pas

    输入文件

    cycle.in

    dancingLessons.in

    digit.in

    输出文件

    cycle.out

    dancingLessons.out

    digit.out

    时间限制

    1000MS

    1000MS

    1000MS

    内存限制

    128MB

    256MB

    256MB

    测试点

    10

    10

    10

    测试点分值

    10

    10

    10

    环上的游戏(cycle)

    有一个取数的游戏。初始时,给出一个环,环上的每条边上都有一个非负整数。这些整数中至少有一个0。然后,将一枚硬币放在环上的一个节点上。两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流取数,取数的规则如下:

    (1)选择硬币左边或者右边的一条边,并且边上的数非0;

    (2)将这条边上的数减至任意一个非负整数(至少要有所减小);

    (3)将硬币移至边的另一端。

    如果轮到一个玩家走,这时硬币左右两边的边上的数值都是0,那么这个玩家就输了。

    如下图,描述的是Alice和Bob两人的对弈过程,其中黑色节点表示硬币所在节点。结果图(d)中,轮到Bob走时,硬币两边的边上都是0,所以Alcie获胜。

    现在,你的任务就是根据给出的环、边上的数值以及起点(硬币所在位置),判断先走方是否有必胜的策略。

    【输入格式】

    第一行一个整数N(N≤20),表示环上的节点数。

    第二行N个数,数值不超过30,依次表示N条边上的数值。硬币的起始位置在第一条边与最后一条边之间的节点上。

    【输出格式】

    仅一行。若存在必胜策略,则输出“YES”,否则输出“NO”。

    【样例】

    cycle.in cycle.out

    4 YES

    2 5 3 0

    cycle.in cycle.out

    3 NO

    0 0 0

    最后取到数的人获胜

    /*
        没找出必败态的判断条件,就打了个暴力
    */
    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define maxn 30
    int n,a[maxn],ans;
    void dfs(int pos,int k){
        if(ans)return;//存在必胜态 
        bool flag=0;
        if(a[pos]!=0){//可以走顺时针方向 
            a[pos]--;
            flag=1;
            dfs((pos+1)%n,!k);
            a[pos]++;
        }
        if(a[(pos-1+n)%n]!=0){//可以走逆时针方向 
            a[(pos-1+n)%n]--;
            flag=1;
            dfs((pos-1+n)%n,!k);
            a[(pos-1+n)%n]++;
        }
        if(!flag&&k==0){
            ans=1;
            return;
        }
    }
    int main(){
        freopen("cycle.in","r",stdin);
        freopen("cycle.out","w",stdout);
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i%n]);
        dfs(0,1);
        if(ans){
            printf("YES");
        }
        else{
            printf("NO");
        }
    }
    70分 暴力
    /*
        本题由于至少存在一个0,所以其实就是考虑一条链的情况
    
        然后可以得出一个显然的结论,如果取一条边,那么一定要将它的权变为0,然后按链长的奇偶得出答案即可
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #include<queue>
    #include<map>
    #define pa pair<int,int>
    #define inf 1000000000
    #define ll long long 
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,l,r;
    int a[50];
    int main()
    {
        //freopen("cycle.in","r",stdin);
        //freopen("cycle.out","w",stdout);
        n=read();r=n;
        for(int i=1;i<=n;i++)a[i]=read();
        while(a[l+1])l++;
        while(a[r])r--;
        r=n-r;
        if(l&1||r&1)puts("YES");
        else puts("NO");
        return 0;
    }
    100分

    舞蹈课(dancingLessons)

    问题描述

    有n个人参加一个舞蹈课。每个人的舞蹈技术由整数来决定。在舞蹈课的开始,他们从左到右站成一排。当这一排中至少有一对相邻的异性时,舞蹈技术相差最小的那一对会出列并开始跳舞。如果相差最小的不止一对,那么最左边的那一对出列。一对异性出列之后,队伍中的空白按原顺序补上(即:若队伍为ABCD,那么BC出列之后队伍变为AD)。舞蹈技术相差最小即是的绝对值最小。

    你的任务是,模拟以上过程,确定跳舞的配对及顺序。

    输入

    第一行为正整数:队伍中的人数。下一行包含n个字符B或者G,B代表男,G代表女。下一行为n个整数。所有信息按照从左到右的顺序给出。在50%的数据中,。

    输出

    第一行:出列的总对数k。接下来输出k行,每行是两个整数。按跳舞顺序输出,两个整数代表这一对舞伴的编号(按输入顺序从左往右1至n编号)。请先输出较小的整数,再输出较大的整数。

    样例输入

    4

    BGBG

    4 2 4 3

    样例输出

    2

    3 4

    1 2

    样例输入

    4

    BGBB

    1 1 2 3

    样例输出

    1

    1 2

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<set>
    #include<queue>
    #include<map>
    #define inf 1000000000
    #define ll long long 
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,ans;
    int a[200005],nxt[200005],pre[200005],a1[200005],a2[200005];
    char ch[200005];
    bool mark[200005];
    struct data{int val,pos;};
    inline bool operator>(data a,data b)
    {
        return a.val>b.val||(a.val==b.val&&a.pos>b.pos);
    }
    void solve()
    {
        priority_queue<data,vector<data>,greater<data> >q;
        for(int i=1;i<n;i++)
            if(ch[i]!=ch[i+1])
                q.push((data){abs(a[i]-a[i+1]),i});
        while(!q.empty())
        {
            int mn=q.top().val,now=q.top().pos;q.pop();
            int l=pre[now],t=nxt[now],r=nxt[t];
            if(mark[now]||mark[t])continue;
            if(abs(a[now]-a[t])!=mn||ch[now]==ch[t])continue;
            mark[now]=mark[t]=1;
            a1[++ans]=now;a2[ans]=t;
            if(l&&r&&ch[r]!=ch[l])
            {
                q.push((data){abs(a[r]-a[l]),l});
            }
            nxt[l]=r;pre[r]=l;
        }
        printf("%d
    ",ans);
        for(int i=1;i<=ans;i++)
            printf("%d %d
    ",a1[i],a2[i]);
    }
    int main()
    {
        //freopen("dancingLessons.in","r",stdin);
        //freopen("dancingLessons.out","w",stdout);
        n=read();mark[0]=1;
        scanf("%s",ch+1);
        for(int i=1;i<=n;i++)a[i]=read();
        for(int i=1;i<n;i++)nxt[i]=i+1;
        for(int i=2;i<=n;i++)pre[i]=i-1;
        solve();
        return 0;
    }
    100分 小根堆+链表

    数位和乘积(digit.cpp/c/pas)

    【题目描述】

    一个数字的数位和乘积为其各位数字的乘积。求所有的N位数中有多少个数的数位和乘积恰好为K。请注意,这里的N位数是可以有前导零的。比如01,02视为二位数,但是他们的数位和乘积都是0。

    【输入格式】

    一行两个整数N,K

    【输出格式】

    一个行一个整数表示结果。

    【样例输入】

    2 3

    【样例输出】

    2

    【样例输入2】

    2 0

    【样例输出2】

    19

    【数据范围】

    对于20%:N <= 6。

    对于50%:N<=16

    存在另外30%:K=0。

    对于100%:N  <= 50,0 <= K <= 10^9。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,k,a[60],cnt;
    int dfs(int pos){
        if(pos==n+1){
            int now=1;
            for(int i=1;i<=n;i++)
                now*=a[i];
            if(now==k)return 1;
            return 0;
        }
        int ans=0;
        for(int i=0;i<=9;i++){
            a[++cnt]=i;
            ans+=dfs(pos+1);
            cnt--;
        }
        return ans;
    }
    int main(){
        //freopen("Cola.txt","r",stdin);
        freopen("digit.in","r",stdin);
        freopen("digit.out","w",stdout);
        scanf("%d%d",&n,&k);
        printf("%d",dfs(1));
    }
    20分 暴力
  • 相关阅读:
    线性基学习笔记
    内网靶机-抓取票据
    域渗透
    flex元素的使用
    webpack 基本使用
    ES模块的导入
    作用域插槽
    具名插槽的使用
    slot插槽的基本使用
    vue中父子组件的访问方式
  • 原文地址:https://www.cnblogs.com/thmyl/p/7416787.html
Copyright © 2020-2023  润新知