第八届福建省大学生程序设计竞赛

版权声明:本文为博主原创文章,未经博主允许不得转载。个人网站独立博客:http://wuyunfeng.cn/ https://blog.csdn.net/hurmishine/article/details/76144848

 Problem A Frog

Accept: 458    Submit: 573
Time Limit: 1000 mSec    Memory Limit : 262144 KB

 Problem Description

Therearex frogs and y chicken in a garden. Kim found there are n heads and m legs in the garden. Please tell Kim how many frogs and chicken are there. (A frog has 4 legs, and a chicken has 2 legs.)

 Input

First line contains an integer T (1 ≤ T ≤ 10), represents there are T test cases.

For each test case: Two number n and m.

1<=n, m <=100000. The data is legal.

 Output

For each test case, output two numbers A and B – the number of frog and the number of chicken.

 Sample Input

22 62 4

 Sample Output

1 10 2

题意:和鸡兔同笼是一个问题。解一个二元一次方程组就可以了。

AC代码:

#include <iostream>
using namespace std;
int main()
{
    int T;
    cin>>T;
    int n,m;
    while(T--)
    {
        cin>>n>>m;
        int t = ((4*n)-m)/2;
        cout<<n-t<<" "<<t<<endl;
    }
    return 0;
}


 Problem B Triangles

Accept: 158    Submit: 754
Time Limit: 1000 mSec    Memory Limit : 262144 KB

 Problem Description

This is a simple problem. Given two triangles A and B, you should determine they are intersect, contain or disjoint. (Public edge or point are treated as intersect.)

 Input

First line contains an integer T (1 ≤ T ≤ 10), represents there are T test cases.

For each test case: X1 Y1 X2 Y2 X3 Y3 X4 Y4 X5 Y5 X6 Y6. All the coordinate are integer. (X1,Y1) , (X2,Y2), (X3,Y3) forms triangles A ; (X4,Y4) , (X5,Y5), (X6,Y6) forms triangles B.

-10000<=All the coordinate <=10000

 Output

For each test case, output “intersect”, “contain” or “disjoint”.

 Sample Input

2
0 0 0 1 1 0 10 10 9 9 9 10
0 0 1 1 1 0 0 0 1 1 0 1

 Sample Output

disjoint intersect

题意:输入两个三角形的坐标,问两个三角形的位置关系,相交,相离和包含。

模板题,代码以后再补。。。。

 Problem D Game

Accept: 145    Submit: 844
Time Limit: 1000 mSec    Memory Limit : 262144 KB

 Problem Description

Alice and Bob is playing a game.

Each of them has a number. Alice’s number is A, and Bob’s number is B.

Each turn, one player can do one of the following actions on his own number:

1. Flip: Flip the number. Suppose X = 123456 and after flip, X = 654321

2. Divide. X = X/10. Attention all the numbers are integer. For example X=123456 , after this action X become 12345(but not 12345.6). 0/0=0.

Alice and Bob moves in turn, Alice moves first. Alice can only modify A, Bob can only modify B. If A=B after any player’s action, then Alice win. Otherwise the game keep going on!

Alice wants to win the game, but Bob will try his best to stop Alice.

Suppose Alice and Bob are clever enough, now Alice wants to know whether she can win the game in limited step or the game will never end.

 Input

First line contains an integer T (1 ≤ T ≤ 10), represents there are T test cases.

For each test case: Two number A and B. 0<=A,B<=10^100000.

 Output

For each test case, if Alice can win the game, output “Alice”. Otherwise output “Bob”.

 Sample Input

4
11111 11
1111112345
54321123 123

 Sample Output

Alice
Bob
Alice
Alice

 Hint

For the third sample, Alice flip his number and win the game.

For the last sample, A=B, so Alice win the game immediately even nobody take a move.

题意:有两个数字,A,B,Alice和Bob先后操作两个数字,(Alice只能操作A,Bob只能操作B)操作的的方式为

1.将这个数反转,eg:123456----->654321

2.将这个数除以10:eg------>123456/10==12345而不是12345.6


思路:这题读清了题目还是挺简单的,只要第二个字符串是第一个字符串的字串就可以了,用strstr会TLE,所以要用KMP,但是,也要注意一个细节。因为可以反转,如果第一次没有匹配成功,将第二个字符串反转在做匹配,但是要把前导0去了,在反转,再做KMP。


网上有人直接先判断字符串长度就可以判断,但是我认为有个bug,

eg:123    123000000

这组数据如果按他们的就是Bob赢。但是确实这样嘛?

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=100000+5;
char a[maxn],b[maxn];
int next[maxn];
int la,lb;
void getNext()
{
    int i=0,j=-1;
    next[0]=-1;//²»ÒªÍü¼Çѽ£¡£¡£¡£¡
    while(i<lb)
    {
        if(j==-1||b[i]==b[j])
        {
            i++,j++;
            next[i]=j;
        }
        else
            j=next[j];
    }
}
int KMP()
{
    int i=0,j=0;
    getNext();
    while(i<la)
    {
        if(j==-1||a[i]==b[j])
            i++,j++;
        else
            j=next[j];
        if(j==lb)
            return i-j+1;
    }
    return -1;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%s%s",a,b);
        la=strlen(a);
        lb=strlen(b);
        /*
        if(la<lb)
        {
            cout<<"Bob"<<endl;
            continue;
        }
        */
        if(KMP()!=-1)
        {
            cout<<"Alice"<<endl;
        }
        else
        {
            for(int i=lb-1;i>=0;i--)
            {
                if(b[i]=='0')
                    b[i]='\0';
                else
                    break;
            }
            lb=strlen(b);
            for(int i=0; i<lb/2; i++)
            {
                swap(b[i],b[lb-1-i]);
            }
            if(KMP()!=-1)
            {
                cout<<"Alice"<<endl;
            }
            else
            {
                 cout<<"Bob"<<endl;
            }
        }
    }
    return 0;
}

 Problem G YYS

Accept: 51    Submit: 221
Time Limit: 1000 mSec    Memory Limit : 262144 KB

 Problem Description

Yinyangshi is a famous RPG game on mobile phones.

Kim enjoys collecting cards in this game. Suppose there are n kinds of cards. If you want to get a new card, you need to pay W coins to draw a card. Each time you can only draw one card, all the cards appear randomly with same probability 1/n. Kim can get 1 coin each day. Suppose Kim has 0 coin and no cards on day 0. Every W days, Kim can draw a card with W coins. In this problem ,we define W=(n-1)!.

Now Kim wants to know the expected days he can collect all the n kinds of cards.

 Input

The first line an integer T(1 ≤ T ≤ 10). There are T test cases.

The next T lines, each line an integer n. (1≤n≤3000)

 Output

For each n, output the expected days to collect all the n kinds of cards, rounded to one decimal place.

 Sample Input

4
1
2
5
9

 Sample Output

1.0
3.0
274.0
1026576.0

题意: 有n张不同的卡片, 每花费W (W = (n - 1)!)个金币可以抽一次卡片, 每种卡片被抽到的概率都是1/n, 求抽到所有不同的卡片, 花费金币数量的期望值.

张数 概率 期望

1 1/n 1

2 (n-1)/n n(n-1)

. .... ....

n 1/n n


期望s = ( n/n + n/(n-1) + n/(n-2) +...+ n )*(n-1)!

 = (1/n + 1/(n-1) + 1/(n-2) +...+ 1/1)*n!


参考博客:http://blog.csdn.net/hnust_xx/article/details/75807071

AC代码:

import java.math.BigInteger;
import java.util.Scanner;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		BigInteger fac[] = new BigInteger[3000+5];
		
		fac[0] = new BigInteger("1");
		for (int i = 1; i <=3000 ; i++) {
			fac[i] = fac[i-1].multiply(BigInteger.valueOf(i));
		}
		
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();
		while(T-->0){
			int n = sc.nextInt();
			BigInteger ans = new BigInteger("0");
			for (int i = 1; i <=n; i++) {
				ans = ans.add(fac[n].divide(BigInteger.valueOf(i)));
			}
			System.out.print(ans);
			System.out.println(".0");
		}
		
	}

}

/**
BigInteger a = BigInteger.valueOf(123);

BigInteger b = new BigInteger("1234656");
*/

Problem K Wand

Accept: 104    Submit: 709
Time Limit: 1000 mSec    Memory Limit : 262144 KB

 Problem Description

N wizards are attending a meeting. Everyone has his own magic wand. N magic wands was put in a line, numbered from 1 to n(Wand_i owned by wizard_i). After the meeting, n wizards will take a wand one by one in the order of 1 to n. A boring wizard decided to reorder the wands. He is wondering how many ways to reorder the wands so that at least k wizards can get his own wand.

For example, n=3. Initially, the wands are w1 w2 w3. After reordering, the wands become w2 w1 w3. So, wizard 1 will take w2, wizard 2 will take w1, wizard 3 will take w3, only wizard 3 get his own wand.

 Input

First line contains an integer T (1 ≤ T ≤ 10), represents there are T test cases.

For each test case: Two number n and k.

1<=n <=10000.1<=k<=100. k<=n.

 Output

For each test case, output the answer mod 1000000007(10^9 + 7).

 Sample Input

2
1 1
3 1

 Sample Output

1
4

题意:抽象过来就是,有n个人,随机打乱顺序后,有多少情况是至少有k个人在正确的位置上。

思路:


错排+组合数学。


设定Dp【i】表示错排的数量。


那么考虑dp转移方程,我们考虑最新加进来的这个数字i:


①如果他放在了位子k上,然后位子k上的这个数字放在了位子i上,那么对应取k个位子有(i-1)种方法,那么有:

Dp【i】=Dp【i-2】*(i-1);


②如果他放在了位子k上,然后位子k上的这个数字没有放置在位子i上,同时位子k上的数字变成了一个新的问题,那么有:

Dp【i】=Dp【i-1】*(i-1);


那么Ans=C(n,n-k)*Dp【n-k】即可;

组合数取余要用逆元。

参考博客:http://blog.csdn.net/mengxiang000000/article/details/75799209

AC代码:

/**
  * 行有余力,则来刷题!
  * 博客链接:http://blog.csdn.net/hurmishine
  * 个人博客网站:http://wuyunfeng.cn/
*/
//http://blog.csdn.net/mengxiang000000/article/details/75799209
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
const int mod = 1e9+7;
LL dp[maxn];
LL fac[maxn];
LL inv[maxn];
LL qmod(LL a,LL b)
{
    LL ans=1;
    while(b)
    {
        if(b&1)
            ans = ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

void Init()
{
    fac[0]=1;
    for(LL i=1;i<maxn;i++)
    {
        fac[i]=(fac[i-1]*i)%mod;
    }
    inv[maxn-1] = qmod(fac[maxn-1],mod-2);
    for(LL i=maxn-2;i>=0;i--)
    {
        inv[i]=(inv[i+1]*(i+1))%mod;
    }

    dp[0]=1;
    dp[1]=0;
    for(LL i=2;i<=10000;i++)
    {
        dp[i]=(i-1)*(dp[i-1]+dp[i-2]);
        dp[i]%=mod;
    }

}
LL C(int n,int m)
{
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
    //freopen("C:\\Users\\17205\\Desktop\\data.txt","r",stdin);
    int T,n,k;
    Init();
    cin>>T;
    while(T--)
    {
        cin>>n>>k;
        LL ans=0;
        for(int i=k;i<=n;i++)
        {
            ans+=C(n,i)*dp[n-i]%mod;
            ans%=mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}

Problem L Tic-Tac-Toe

Accept: 248    Submit: 552
Time Limit: 1000 mSec    Memory Limit : 262144 KB

 Problem Description

Kim likes to play Tic-Tac-Toe.

Given a current state, and now Kim is going to take his next move. Please tell Kim if he can win the game in next 2 moves if both player are clever enough.

Here “next 2 moves” means Kim’s 2 move. (Kim move,opponent move, Kim move, stop).

Game rules:

Tic-tac-toe (also known as noughts and crosses or Xs and Os) is a paper-and-pencil game for two players, X and O, who take turns marking the spaces in a 3×3 grid. The player who succeeds in placing three of their marks in a horizontal, vertical, or diagonal row wins the game.

 Input

First line contains an integer T (1 ≤ T ≤ 10), represents there are T test cases.

For each test case: Each test case contains three lines, each line three string(“o” or “x” or “.”)(All lower case letters.)

x means here is a x

o means here is a o

. means here is a blank place.

Next line a string (“o” or “x”) means Kim is (“o” or “x”) and he is going to take his next move.

 Output

For each test case:

If Kim can win in 2 steps, output “Kim win!”

Otherwise output “Cannot win!”

 Sample Input

3
. . .
. . .
. . .
o
o x o
o . x
x x o
x
o x .
. o .
. . x
o

 Sample Output

Cannot win!
Kim win!
Kim win!

题意:Kim在玩这个游戏,输入这个游戏的目前状态,问你Kim两步之内能赢吗?

思路:

1.Kim要赢,之前棋盘上他的棋子至少要有2颗。

2.有可能Kim再下一步就赢了,所以要枚举没有的空白棋盘,判断Kim是否能赢。

3. 此时,若kim要赢,必须下两步,由于两个人都非常聪明,在kim先下一步之后,对手可能阻止Kim。。。

所以我们换个思路。。。。。

Kim下了一步之后,再下一步(忽略对手的那一步),如果此时Kim赢的方式大于等于2,则Kim一定赢。因为对手只能阻止一种情况的发生。

AC代码:

#include <iostream>
#include <cstring>
using namespace std;
char a[5][5];
char ch;
int getCnt()
{
    int cnt=0;
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            if(a[i][j]==ch)
                cnt++;
        }
    }
    return cnt>=2;
}
bool check()
{
    for(int i=0;i<3;i++)
    {
        if(a[i][0]==ch&&a[i][0]==a[i][1]&&a[i][0]==a[i][2])
            return true;
    }
    for(int j=0;j<3;j++)
    {
        if(a[0][j]==ch&&a[0][j]==a[1][j]&&a[0][j]==a[2][j])
            return true;
    }
    if(a[0][0]==ch&&a[0][0]==a[1][1]&&a[0][0]==a[2][2])
        return true;
    if(a[0][2]==ch&&a[0][2]==a[1][1]&&a[0][2]==a[2][0])
        return true;
    return false;
}
bool two()
{
    int cnt=0;
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            if(a[i][j]=='.')
            {
                a[i][j]=ch;
                if(check())
                {
                    cnt++;
                }
                a[i][j]='.';
            }
        }
    }
    return cnt>1;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int cnt=0;
        for(int i=0;i<3;i++)
        {
            for(int j=0;j<3;j++)
                cin>>a[i][j];
        }
        cin>>ch;
        if(!getCnt())
        {
            cout<<"Cannot win!"<<endl;
            continue;
        }
        bool oneFlag=false;
        for(int i=0;!oneFlag&&i<3;i++)
        {
            for(int j=0;!oneFlag&&j<3;j++)
            {
                if(a[i][j]=='.')
                {
                    a[i][j]=ch;
                    oneFlag = check();
                    a[i][j]='.';
                }
            }
        }
        if(oneFlag)
        {
            cout<<"Kim win!"<<endl;
            continue;
        }
        bool flagTwo=false;
        for(int i=0;!flagTwo&&i<3;i++)
        {
            for(int j=0;!flagTwo&&j<3;j++)
            {
                if(a[i][j]=='.')
                {
                    a[i][j]=ch;
                    if(two())
                    {
                        flagTwo=true;
                    }
                    a[i][j]='.';
                }
            }
        }
        if(flagTwo)
            cout<<"Kim win!"<<endl;
        else
            cout<<"Cannot win!"<<endl;
    }
    return 0;
}


阅读更多
换一批

没有更多推荐了,返回首页