Gym 102263 ArabellaCPC 2019

Gym 102263 ArabellaCPC 2019

  • A Is It Easy ?(签到)
  • B Road to Arabella(博弈论)
  • C Check The Text(模拟)
  • D Meeting Bahosain(思维)
  • E
  • F
  • G Card Game
  • H Steaks(思维)
  • I Bashar and Hamada
  • J Thanos Power(dp)
  • K
  • L
  • M Two Operations(模拟)

A Is It Easy ?(签到)

题意:略

题记:略

#include

using namespace std;

int main(){
     
    int n,k;
    cin>>n>>k;
    cout<<n*k<<endl;
    return 0;
}

B Road to Arabella(博弈论)

题意:给一个n和k,每个人每次可以从max(1,n-k)中选一个数,然后把n减去这个数。n为0时游戏结束。

题记:
当n=k+1或者n=k时,选的那个数只能为1。只要这时的n是偶数,那么每次轮到Ayoub选时n都是奇数,轮到Kilani选时n都是奇数,那么Ayoub是必胜的。

当n>k+1时Kilani永远是必胜态,因为他可以让自己选的时候n为奇数。

#include

using namespace std;

int main(){
     
    int t;
    cin>>t;
    while(t--){
     
        int n,k;
        cin>>n>>k;
        if((n==k||n-1==k)&&n%2==0)
            cout<<"Ayoub"<<endl;
        else
            cout<<"Kilani"<<endl;
    }
    return 0;
}

C Check The Text(模拟)

题意:让你模拟键盘输入的过程,然后判断输入的字符串是否和原字符串匹配。

题记:用栈模拟一下即可。

#include

using namespace std;
char a[5000];
int main(){
     
    int n,k=0;
    cin>>n;
    for(int i=0;i<n;i++){
     
        string s;
        cin>>s;
        for(int j=0;j<s.size();j++)
            a[k++]=s[j];
        if(i!=n-1) a[k++]=' ';
    }
    stack<char> ss;
    int m,flag=1;
    cin>>m;
    char s[10];
    while(m--){
     
        cin>>s;
        if(s[0]=='C')
            flag=!flag;
        else if(s[0]=='B'){
     
            if(ss.size()!=0)
                ss.pop();
        }
        else if(s[0]=='S')
            ss.push(' ');
        else{
     
            if(flag)
                ss.push(s[0]);
            else
                ss.push(s[0]-32);
        }
    }
    bool ans=true;
    //cout<
    if(ss.size()!=k)
        ans=false;
    else{
     
      for(int i=k-1;i>=0;i--){
     
          char c=ss.top();
          ss.pop();
          //cout<
          //cout<
          if(a[i]!=c){
     
              ans=false;
              break;
          }
     }
    }
    if(ans) cout<<"Correct"<<endl;
    else cout<<"Incorrect"<<endl;
    return 0;
}

D Meeting Bahosain(思维)

题意:将a数组中的数加上或减去b数组中的数,使得a数组中所有的数都相同。

题记:求出两个数组的最大公因数,然后看一下g1能不能被g2整除即可。

#include

using namespace std;

int main(){
     
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n,m;
    cin>>n>>m;
    int g1,g2;
    for(int i=0;i<n;i++){
     
        int x;
        cin>>x;
        if(!i)
            g1=x;
        else
            g1=__gcd(g1,x);
    }
    for(int i=0;i<m;i++){
     
        int x;
        cin>>x;
        if(!i)
            g2=x;
        else
            g2=__gcd(g2,x);
    }
    //cout<
    if(g1%g2==0||n==1)
        cout<<"Yes"<<endl;
    else
        cout<<"No"<<endl;
    return 0;
}

E

F

G Card Game

题意:求出所有可能的期望值

题记:首先当我选了一个数i,那么只有i-1个数是对结果又贡献的。例如选一个3,那么只有对方选择1或者2这两张卡我才能得到3这个分数。那么(i-1)*i/n就是这个分数的期望值,把所有分数的期望值加起来就是答案。

```c
#include

using namespace std;

int main(){
     
    double n;
    scanf("%lf",&n);
    double ans=0;
    for(double i=2;i<=n;i++)
        ans+=(i-1)*i/n;
    printf("%.10f\n",ans);
    return 0;
}

H Steaks(思维)

题意:一个锅可以同时煎两块牛排,煎一面需要5分钟,有k个锅和n块牛排,求需要煎多久。

题记:分为2种情况。

1、牛排数量不超过2*k,那么10分钟可以煎完。

2、牛排数量超过了2*k,那么平均煎每块牛排的时间其实还是5分钟(仔细理解样例)。所以只需要把n/k(需要向上取整)*5即可。

#include

using namespace std;
typedef long long ll;
int main(){
     
    ll n,k;
    cin>>n>>k;
    if(k*2>=n)
        cout<<10<<endl;
    else
        cout<<(n+k-1)/k*5;
    return 0;
}

I Bashar and Hamada

J Thanos Power(dp)

题意:每次操作可以加上或者减去10x。最少需要多少次操作能得到n。

题记:每一位数都有两种情况,一种是从高位减下来,一种是从低位加上去。
例如:n=4
4=100+100+100+100
4=101-100-100-100-100-100-100
显然,从低位往上加需要n次操作,从高位往下需要10-n+1次操作。
那么我们只要把每一位数都存下来,然后求出每一位数的最优解即可得到答案(局部最优得到全局最优)。
dp[0][i]表示第i位从高位往下需要的操作次数
dp[1][i]表示第i为从低位往上需要的操作次数

dp[1][i]=a[i]+min(dp[0][i-1],dp[1][i-1])
由于从高位往下,所以第i-1位的数是需要加一的。
由于dp[0][i-1]也是从高位往下的,所以dp[0][i-1]的操作可以减一,dp[1][i-1]则需要加一。

例如:28
dp[0][0]=9
dp[1][0]=2

dp[0][1]=8+min(9,2)
dp[1][1]=10-8+min(9-1,2+1)
第二位8是从高位往下的,那么第一位的数需要是3,所以dp[0][0]=9-1,dp[1][0]=2+1
最后答案取dp[1][len-1]和dp[0][len-1]的最小值即可。

#include

using namespace std;
const int N=1e5+10;
int a[N];
int dp[2][N];
int main(){
     
    string s;
    cin>>s;
    int len=s.size();
    for(int i=0;i<len;i++)
        a[i]=s[i]-'0';
    dp[0][0]=10-a[0]+1;
    dp[1][0]=a[0];
    for(int i=1;i<len;i++){
     
        dp[1][i]=a[i]+min(dp[0][i-1],dp[1][i-1]);
        dp[0][i]=10-a[i]+min(dp[0][i-1]-1,dp[1][i-1]+1);
    }
    cout<<min(dp[1][len-1],dp[0][len-1]);
    return 0;
}

K

L

M Two Operations(模拟)

题意:每两个相同的字母可以进位,除了z,因为z是最高位。求进位之后的字典序最大的答案。

题记:桶牌记录每个字母出现的次数,然后从低位开始进位,最后从高位到低位输出即可。

#include

using namespace std;
const int N=1e5+10;
int vis[N];
int main(){
     
    string s;
    cin>>s;
    int len=s.size();
    for(int i=0;i<len;i++){
     
        //int t=s[i]-'a';
        //cout<
        vis[s[i]-'a']++;
    }
    for(int i=0;i<25;i++){
     
        vis[i+1]+=vis[i]/2;
        vis[i]%=2;
    }
    for(int i=25;i>=0;i--){
     
        while(vis[i]--){
     
            cout<<char(i+'a');
        }
    }
    cout<<endl;
    return 0;
}

你可能感兴趣的:(codeforces)