9.29noip模拟试题

 

环上的游戏(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

2 5 3 0 YES

cycle.in cycle.out

3

0 0 0 NO

最后取到数的人获胜

 博弈

/*
比较简单的博弈题
手动模拟一下 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,a[50],s;
int main()
{
    freopen("cycle.in","r",stdin);
    freopen("cycle.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        if(a[i]==0)break;
        else s++;
    for(int i=n;i>=1;i--)
        if(a[i]==0)break;
        else s++;
    if(s&1)printf("YES
");
    else printf("NO
");
    return 0;
}
View Code

舞蹈课(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

 贪心

/*
贪心+堆优化
一开始把所有挨着的男女放进去
然后拿出Abs最小的 同时看看新生成的挨着的能不能组合成一组
注意一些细节的处理
开始wa了一个点 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define maxn 200010
#define inf 0x7fffffff
using namespace std;
int n,a[maxn],cnt,f[maxn],s1,s2;
char c[maxn];
struct node{
    int l,r,C;
    bool operator < (const node &x) const{
        if(x.C==C)return x.l<l;
        return x.C<C;
    }
}ans[maxn],t;
priority_queue<node>q;
int init(){
    int x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
int Abs(int x){
    return x<0?-x:x;
}
int main()
{
//    freopen("dancingLessons.in","r",stdin);
    //freopen("dancingLessons.out","w",stdout);
    n=init();
    scanf("%s",c+1);
    for(int i=1;i<=n;i++)
        if(c[i]=='B')s1++;
        else s2++;
    for(int i=1;i<=n;i++)
        a[i]=init();
    for(int i=2;i<=n;i++)
        if(c[i-1]!=c[i])
            q.push((node){i-1,i,Abs(a[i]-a[i-1])});
    while(!q.empty()){
        int falg=0;
        while(1){
            if(q.empty()){falg=1;break;}
            t=q.top();q.pop();
            if(f[t.l]||f[t.r])continue;
            else break;
        }
        if(q.empty()&&falg)break;//这里多一个falg标记 表示q空时最后一个合不合法 
        ans[++cnt].l=t.l;ans[cnt].r=t.r;
        f[t.l]=1;f[t.r]=1;
        int L=t.l-1,R=t.r+1;
        while(f[L])L--;
        while(f[R])R++;
        if(L&&R<=n&&c[L]!=c[R])
            q.push((node){L,R,Abs(a[R]-a[L])});
    }
    printf("%d
",cnt);
    for(int i=1;i<=cnt;i++)
        printf("%d %d
",ans[i].l,ans[i].r);
    return 0;
}
View Code

数位和乘积(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。

 暴力50

/*
我是蒟蒻没有想出正解...
打了个暴力 当然也不是裸裸的
k==0 10^n-9^n 
分成两段 每段分别暴力 在hash一下(不知为啥hash最小的数据不对 写了map)
还有一些小剪枝
目测n<=15的都能过
但是说好的%30<=16结果全尼玛是16 你故意的吧
然后就只拿到了基础的暴力分50 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<ctime>
#define mod 233333
using namespace std;
int n,k,N,falg,ans[100],J[100];
map<int,int>p;
void Add(int a[100],int b[100]){
    int c[30];
    memset(c,0,sizeof(c));
    int len=max(a[0],b[0]);
    for(int i=1;i<=len;i++)
        c[i]=a[i]+b[i];
    for(int i=1;i<=len;i++)
        if(c[i]>9){
            c[i+1]++;c[i]%=10;
        }
    if(c[len+1])len++;c[0]=len;
    for(int i=0;i<=len;i++)a[i]=c[i];
}
void Jian(int a[100],int b[100]){
    int c[100];
    memset(c,0,sizeof(c));
    int len=max(a[0],b[0]);
    for(int i=1;i<=len;i++)
        c[i]=a[i]-b[i];
    for(int i=1;i<=len;i++)
        if(c[i]<0){
            c[i+1]--;c[i]+=10;
        }
    for(int i=len;i>=0;i--)
        if(c[i]){
            c[0]=i;break;
        }
    for(int i=0;i<=len;i++)a[i]=c[i];
}
void Mul(int a[100],int x){
    int c[100];
    memset(c,0,sizeof(c));
    int len=a[0];
    for(int i=1;i<=len;i++)
        c[i]=a[i]*x;
    for(int i=1;i<=len;i++)
        if(c[i]>9){
            c[i+1]+=c[i]/10;
            c[i]%=10;
        }
    while(c[len+1]>9){
        len++;
        c[len+1]+=c[len]/10;
        c[len]%=10;
    }
    if(c[len+1])len++;c[0]=len;
    for(int i=0;i<=len;i++)a[i]=c[i];
}
void Cal(int x){
    int a[100];
    memset(a,0,sizeof(a));
    while(x){
        a[++a[0]]=x%10;x/=10;
    }
    Add(ans,a);
}
void Dfs(int now,int s,int r){
    if(r>k)return;
    if(now==N+1){
        if(!falg)p[r]++;
        else{
            if(r){
                int t=k/r;
                if(t*r==k)Cal(p[t]);
            }
        }
        return;
    }
    for(int i=1;i<=9;i++)
        Dfs(now+1,s*10+i,r*i);
}
void Solve(){
    ans[0]=1;ans[1]=1;
    J[0]=1;J[1]=1;
    for(int i=1;i<=n;i++)
        Mul(ans,10);
    for(int i=1;i<=n;i++)
        Mul(J,9);
    Jian(ans,J);
}
int main()
{
    //freopen("digit.in","r",stdin);
    //freopen("digit.out","w",stdout);
    scanf("%d%d",&n,&k);
    if(k==0)Solve();
    else{
        N=n/2;Dfs(1,0,1);
        falg=1;
        N=n;Dfs(n/2+1,0,1);
    }
    for(int i=max(ans[0],1);i>=1;i--)
        printf("%d",ans[i]);
    return 0;
}
View Code

正解dp

/*
正解还是很机智的Orz
f[i][j][k][l][r]前i位选了j个2 k个3 l个5 r个7的方案数
然后+个高精就ok了 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,k,ans[100],J[100];
int f[32][32][32][32][40];
void Add(int a[100],int b[100]){
    int c[30];
    memset(c,0,sizeof(c));
    int len=max(a[0],b[0]);
    for(int i=1;i<=len;i++)
        c[i]=a[i]+b[i];
    for(int i=1;i<=len;i++)
        if(c[i]>9){
            c[i+1]++;c[i]%=10;
        }
    if(c[len+1])len++;c[0]=len;
    for(int i=0;i<=len;i++)a[i]=c[i];
}
void Jian(int a[100],int b[100]){
    int c[100];
    memset(c,0,sizeof(c));
    int len=max(a[0],b[0]);
    for(int i=1;i<=len;i++)
        c[i]=a[i]-b[i];
    for(int i=1;i<=len;i++)
        if(c[i]<0){
            c[i+1]--;c[i]+=10;
        }
    for(int i=len;i>=0;i--)
        if(c[i]){
            c[0]=i;break;
        }
    for(int i=0;i<=len;i++)a[i]=c[i];
}
void Mul(int a[100],int x){
    int c[100];
    memset(c,0,sizeof(c));
    int len=a[0];
    for(int i=1;i<=len;i++)
        c[i]=a[i]*x;
    for(int i=1;i<=len;i++)
        if(c[i]>9){
            c[i+1]+=c[i]/10;
            c[i]%=10;
        }
    while(c[len+1]>9){
        len++;
        c[len+1]+=c[len]/10;
        c[len]%=10;
    }
    if(c[len+1])len++;c[0]=len;
    for(int i=0;i<=len;i++)a[i]=c[i];
}
void Cal(int x){
    int a[100];
    memset(a,0,sizeof(a));
    while(x){
        a[++a[0]]=x%10;x/=10;
    }
    Add(ans,a);
}
void Solve(){
    ans[0]=1;ans[1]=1;
    J[0]=1;J[1]=1;
    for(int i=1;i<=n;i++)
        Mul(ans,10);
    for(int i=1;i<=n;i++)
        Mul(J,9);
    Jian(ans,J);
    for(int i=max(ans[0],1);i>=1;i--)
        printf("%d",ans[i]);
}
void solve(){
    int t1=0,t2=0,t3=0,t4=0;
    while(k%2==0)k/=2,t1++;
    while(k%3==0)k/=3,t2++;
    while(k%5==0)k/=5,t3++;
    while(k%7==0)k/=7,t4++;
    if(k>1){cout<<0;return;}
    f[0][0][0][0][0]=1;
    f[0][0][0][0][1]=1;
    for(int i=1;i<=n;i++)
        for(int j=t1;j>=0;j--)
            for(int k=t2;k>=0;k--)
                for(int l=t3;l>=0;l--)
                    for(int r=t4;r>=0;r--){
                        if(j>=1)Add(f[j][k][l][r],f[j-1][k][l][r]);//2
                        if(k>=1)Add(f[j][k][l][r],f[j][k-1][l][r]);//3
                        if(j>=2)Add(f[j][k][l][r],f[j-2][k][l][r]);//4
                        if(l>=1)Add(f[j][k][l][r],f[j][k][l-1][r]);//5
                        if(j>=1&&k>=1)Add(f[j][k][l][r],f[j-1][k-1][l][r]);//6
                        if(r>=1)Add(f[j][k][l][r],f[j][k][l][r-1]);//7
                        if(j>=3)Add(f[j][k][l][r],f[j-3][k][l][r]);//8
                        if(k>=2)Add(f[j][k][l][r],f[j][k-2][l][r]);//9
                    }
    for(int i=max(f[t1][t2][t3][t4][0],1);i>=1;i--)
        printf("%d",f[t1][t2][t3][t4][i]);
}
int main()
{
    //freopen("digit.in","r",stdin);
    //freopen("digit.out","w",stdout);
    scanf("%d%d",&n,&k);
    if(k==0)Solve();
    else solve();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/yanlifneg/p/5920076.html