省赛训练2


A - A FZU - 2272

题意:

鸡兔同笼,水题。

代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int T,n,m;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        int x=(4*n-m)/2;
        int y=n-x;
        cout<<y<<" "<<x<<endl;
    }
    return 0;
}

D - D FZU - 2275

题意思路:

给你两个字符串,a和b,对a进行两种操作,(1)顺序颠倒(2)处于10(相当于去掉最后一位)。注意此处有个很大的坑,只要字符串b为一个0时,则一定可以变换成,例如 111 、11、 1均可以得到0,因为最后一个数1除于10得到的为0.另外就是b的长度一定要小于a的长度,否则不会变换成,其余的情况就用kmp算法来在a串里面寻找b串,看能否找到,找到即可变换而成,否则就不能变换成

代码:

#include<iostream>
#include<cstring>
using namespace std;
const int MAX=10000010;
int f[MAX];
char a[MAX], b[MAX], c[MAX];
int Find(char *T, char *P, int n, int m)
{
    int i=0, k=0;
    while(i<n)
    {
        if(k==-1 || T[i]==P[k])
        {
            i++;    
            k++;
            if(k==m)
                return 1;
        }
        else
            k=f[k];
    }
    return 0;
}
void getFail(char *P, int m)
{
    f[0]=-1;
    int temp=-1;
    int j=0;
    while(j<m)
    {
        if(temp==-1 || P[j]==P[temp])
        {
            j++;
            temp++;
            f[j]=temp;
        }
        else
            temp=f[temp];
    }
}
int main()
{

    int T;
    cin>>T;
    while(T--)
    {
        cin>>a>>b;
        int la=strlen(a), lb=strlen(b);
         if(b[0]=='0'&&lb==1){
         cout<<"Alice"<<endl;
         continue;
         }
        if(lb>la){
            cout<<"Bob"<<endl;
            continue;
        }
        for(int i=0; i<lb; i++)
        {
            c[i]=b[lb-1-i];
        }
        int flag=0;
        getFail(b, lb);
        flag=Find(a, b, la, lb);
        if(flag==0)
        {
            getFail(c, lb);
            flag=Find(a, c, la, lb);
        }
        if(flag==0)
        {
            cout<<"Bob"<<endl;
        }
        else
        {
            cout<<"Alice"<<endl;
        }
    }
    return 0;
}

G - G FZU - 2278

题意:

有n种卡片,如果你想获得其中一种就得花费W金币,每次只能得到一种,并且得到每一种的概率都是1/n,问你得到n种卡片期望的天数是多少?

思路:

其实就是第一天 n/n * w 第二天 (n-1/n ) * w 所以得到一种是(n/n-1)*w,第二天(n-2/n)*w即得到一种:(n/n-2)*w....

即可推出一个公式: w*(n/n+n/n-1+n/n-2+...n)即n!(1+1/2+1/3+1/4+...+1/n)因为数据太大,用的Java大数

代码:

import java.math.BigInteger;
import java.util.*;

public class Main
{
  public static void main(String args[])
  {
      Scanner cin = new Scanner(System.in);
      BigInteger c[]=new BigInteger[3005];
      c[0] = BigInteger.ONE;
      for(int i=1;i<=3000;i++)
      {
    	  c[i] = c[i-1].multiply( BigInteger.valueOf(i) ); 
      }
      int T=cin.nextInt();
      while(T-->0)
      {
    	  int n = cin.nextInt();
    	  BigInteger sum = BigInteger.ZERO;
    	  for(int i=1;i<=n;i++) {
    		  sum=sum.add(c[n].divide(BigInteger.valueOf(i)));
    	  }
      System.out.print(sum);
      System.out.println(".0");
     }
  }
}

J - J FZU - 2281

题意:

题意有n天,有一个物品的价格会每天浮动,每天的价格ai(1<=i<=n),在一开始你有m元RMB,在每一天,你可以以ai的价格买进任意个物品,也可以以ai的价格卖出任意个物品,前提是你有足够的钱和足够的物品,问你在n天后最多能获得多少钱?最后的答案要mod1e9+7


思路:

简单的贪心,价格变化化成一张折线图就是不停的上下浮动,我们每一次总是在价格在低谷的时候买进,价格在低谷对应的高峰的时候卖出这样整一个序列我们只需要找出每一个递增的连续子序列就可以了,由于数据较大,所以使用了Java


代码:

import java.math.BigInteger;
import java.util.*;

public class Main
{
  public static void main(String args[])
  {
      Scanner cin = new Scanner(System.in);
      
      long n;
      BigInteger m=null;
      long MOD=1000000007;
      BigInteger c[]=new BigInteger[2005];
      int T,cas=0;
      T=cin.nextInt();
      while(T-->0)
      {
    	  n=cin.nextLong();
    	  m = cin.nextBigInteger();
          for(int i=1;i<=n;i++)
             c[i]=cin.nextBigInteger();
           c[(int) (n+1)]=BigInteger.valueOf(-1);
           int s,t=0;
           s=1;
              while(s<=n) //找最大值、最小值
              {
                  for(int i=s+1;i<=n+1;i++)
                  {
                      if(c[i].compareTo(c[i-1])<0)
                      {
                          t=i-1;
                          break;
                      }
                  }
                  BigInteger num=m.divide(c[s]);
                  m=m.mod(c[s]);
                  m=m.add(c[t].multiply(num));
                  s=t+1;
              }
             System.out.println("Case #"+(++cas)+": "+m.mod(BigInteger.valueOf(MOD)));
       }
      
      cin.close();
      
     
  }
}

L-L  FZU-2283

题意:

给你一个3*3的井字棋,判断Kim是否能够通过两步 。 赢得对手。两步赢得对手的步骤是:Kim下,对方下,Kim下。

如果棋子能够三连就算Kim赢。

思路:

①首先我们暴力枚举一个位子,使得这个位子就是Kim下的位子。
②然后check一下是否能够胜利。
③然后我们不枚举对方的走法,因为对方要足够聪明,所以我们枚举Kim下一步走哪里会赢,如果有这样一个位子,对手肯定要阻拦。那么怎样的条件对方阻拦不了Kim的胜利呢?就是Kim下一步,如果有两个位子以上的放置方案会赢,那么对手如何阻拦都不行了。

④过程模拟一下即可

代码:

#include <iostream>
using namespace std;
int mp[10];
int kim;
int flag;
int vis[5];
int check()
{
    if(mp[1] == mp[2] && mp[2]==mp[3] && mp[3] == kim)
    {
        return 1;
    }
    if(mp[4] == mp[5] && mp[5] ==mp[6] && mp[6] == kim)
    {
        return 1;
    }
    if(mp[7] == mp[8] && mp[8] == mp[9] && mp[9] == kim)
    {
        return 1;
    }
    if(mp[1] == mp[5] && mp[5] == mp[9] && mp[9] ==kim)
    {
        return 1;
    }
    if( mp[3] == mp[5] && mp[5] == mp[7] && mp[7] == kim)
    {
        return 1;
    }
    if(mp[1] == mp[4] && mp[4] == mp[7] && mp[7] ==kim)
    {
        return 1;
    }
    if(mp[2] == mp[5] && mp[5] ==mp[8] && mp[8] == kim)
    {
        return 1;
    }
    if(mp[3] == mp[6] && mp[6] ==mp[9] && mp[9] == kim)
    {
        return 1;
    }
    return 0;
}

int judge()
{
    if( check()==1 ) return 1;
    int tot=0;
    for(int i=1;i<=9;i++)
    {
        if(mp[i]==0)
        {
            mp[i] = kim;
            if(check()==1)
            {
                tot++;
            }
            mp[i]=0;
        }
    }
    if(tot >= 2) return 1;
    else return 0;
}

int main()
{
    int t;
    char ch;
    cin>>t;
    while(t--)
    {
        for(int i=1;i<=9;i++)
        {
            cin>>ch;
            if(ch=='.') mp[i] = 0;
            else if(ch == 'x') mp[i] = 1;
            else mp[i] = 2;
        }
        cin>>ch;
        if(ch=='.') kim=0;
        else if(ch == 'x') kim=1;
        else kim = 2;
        flag = 0;
        for(int i=1; i<=9; i++)
        {
            if(mp[i] == 0)
            {
                mp[i] = kim;
                if(judge() == 1)
                {
                    flag = 1;
                }
                mp[i] = 0;
            }
        }
        if(flag==1) cout<<"Kim win!"<<endl;
        else cout<<"Cannot win!"<<endl;
    }
    return 0;
}








  • T = I-1;打破
  • ,所以我们枚举Kim下一步走哪里会赢

猜你喜欢

转载自blog.csdn.net/sinat_37668729/article/details/80113831