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

A:水题

B:判断两个三角形是相交相含相离

C:用了好久才搞懂题意的我。然后就没有然后了。后来题解也没有搜到。想用差分约束或者类似于网络流的东西搞一搞

D:BOb和alice的游戏。由于要判断串a中有无串b,所以要用到kmp。

坑点在于串b很可能有后缀0,这样翻转后就没了。我们队当时没考虑到这个问题WA了很多发

具体看代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 2000009;
int t, f[MAXN], f2[MAXN], lens, lenss;
char s[MAXN], ss[MAXN];
void getfail()
{
	f[0] = f[1] = 0;
	for (int i = 1; i < lenss; ++i) {
		int j = f[i];
		while (j && ss[i] != ss[j]) j = f[j];
		f[i + 1] = (ss[i] == ss[j] ? j + 1 : 0);
	}
}
int find()
{
	int j = 0;
	for (int i = 0; i < lens; ++i) {
		while (j && ss[j] != s[i]) j = f[j];
		if (ss[j] == s[i]) ++j;
		if (j == lenss) return 1;
	}
	return 0;
}
int main()
{
	scanf("%d", &t);
	while (t--) {
		int flag = 0;
		scanf("%s %s", s, ss);
		if (strcmp(s, ss) == 0) {
			puts("Alice");
			continue;
		}
		lenss = strlen(ss);
		lens = strlen(s);
		while (lenss && ss[lenss - 1] == '0') {
			ss[lenss - 1] = '\0';
			--lenss;
		}
		getfail();
		if (find()) flag = 1;
		reverse(s, s + lens);
		if (find()) flag = 1;
		if (flag) puts("Alice");
		else puts("Bob");
	}
	return 0;
}

E:没看

F:树状数组或者线段树搞一搞。待补

G:期望题。

类似于:百事世界杯之旅

import java.math.BigInteger;
import java.util.Scanner;
public class Main {

	public static void main(String[] args) {
		int n,t;
		Scanner sc=new Scanner(System.in);
		t=sc.nextInt();
		
		for(int j=1;j<=t;j++)
		{
			BigInteger num=BigInteger.ONE;
			n=sc.nextInt();
			for(int i=1;i<=n;i++)
			{
				num=num.multiply(BigInteger.valueOf(i));
			}
			//System.out.println(num);
			BigInteger ans=BigInteger.ZERO;
			for(int i=1;i<=n;i++)
			{
				ans=ans.add(num.divide(BigInteger.valueOf(i)));
		    }
			System.out.println(ans+".0");
		}
	}
}

H:不会

I:预处理了一下长度,1921ms卡过。不过是赛后想到的

Kim is a magician, he can use n kinds of magic, number from 1 to n. We use string Si to describe magic i. Magic Si will make Wi points of damage. Note that Wi may change over time.


Kim obey the following rules to use magic:


Each turn, he picks out one magic, suppose that is magic Sk, then Kim will use all the magic i satisfying the following condition:


1. Wi<=Wk


2. Sk is a suffix of Si.


Now Kim wondering how many magic will he use each turn.


Note that all the strings are considered as a suffix of itself.


Input
First line the number of test case T. (T<=6)


For each case, first line an integer n (1<=n<=1000) stand for the number of magic.


Next n lines, each line a string Si (Length of Si<=1000) and an integer Wi (1<=Wi<=1000), stand for magic i and it’s damage Wi.


Next line an integer Q (1<=Q<=80000), stand for there are Q operations. There are two kinds of operation.


“1 x y” means Wx is changed to y.


“2 x” means Kim has picked out magic x, and you should tell him how many magic he will use in this turn.


Note that different Si can be the same.


Output
For each query, output the answer.


Sample Input
1
5
abracadabra 2
adbra 1
bra 3
abr 3
br 2
5
2 3
2 5
1 2 5
2 3
2 2
Sample Output
3
1
2
1

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
struct node
{
    char h[1010];
    int len;
    int cnt;
}lala[1010];
int main()
{
    int t,n;
    int q;
    int aa,bb,cc;
    scanf("%d",&t);
    while(t--)
    {
       scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            //cin>>lala[i].h>>lala[i].cnt;
             scanf("%s%d",lala[i].h,&lala[i].cnt);
            lala[i].len=strlen(lala[i].h);
        }
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
           scanf("%d",&aa);
            if(aa==1)
            {
               scanf("%d%d",&bb,&cc);
                lala[bb].cnt=cc;
            }
            else
            {
                scanf("%d",&bb);
                int cntt=0;
                for(int z=1;z<=n;z++)
                {
                    int flag=0;
                    if(lala[z].len<lala[bb].len||lala[z].cnt>lala[bb].cnt)
                        continue;
                    else
                    {
                        //cout<<lala[z].len-1-lala[bb].len<<"*****"<<endl;
                        //string kaka=lala[bb].h.substr(lala[z].len-1-lala[bb].len,lala[bb].len);
                        for(int j=lala[bb].len-1, kk=lala[z].len-1;j>=0;j--,kk--)
                        {
                            if(lala[bb].h[j]!=lala[z].h[kk])
                            {
                                flag=1;
                                break;
                            }
                        }
                        if(flag==0)
                            cntt++;
                    }
                }
                printf("%d\n",cntt);
            }
        }
    }
    return 0;
}

J:This is a very easy problem.


ACMeow loves GTX1920. Now he has m RMB, but no GTX1920s. In the next n days, the unit price of GTX1920 in the ith day is Ci RMB. In other words, in the ith day, he can buy one GTX1920 with Ci RMB, or sell one GTX1920 to gain Ci RMB. He can buy or sell as many times as he wants in one day, but make sure that he has enough money for buying or enough GTX1920 for selling.


Now he wants to know, how many RMB can he get after the n days. Could you please help him?


It’s really easy, yeah?


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


For each test case: first line contains two integers n(1 ≤ n ≤2000) and m(0 ≤ m ≤1000000000). Following n integers in one line, the ith integer represents Ci(1 ≤ Ci ≤1000000000).


Output
For each test case, output "Case #X: Y" in a line (without quotes), where X is the case number starting from 1, and Y is the maximum number of RMB he can get mod 1000000007.


Sample Input
2
3 1
1 2 3
4 1
1 2 1 2
Sample Output
Case #1: 3

Case #2: 4

主要就是可以买卖很多次。

思路:谷底买,谷峰卖。细节

具体看代码:

import java.math.BigInteger;
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		int t,cas=0;
		Scanner sc=new Scanner(System.in);
		t=sc.nextInt();
		int []a=new int[2005];
		BigInteger haha=BigInteger.valueOf(0);
		int anaaa=0;
		while((t--)>0)
		{
			anaaa++;
			int n=sc.nextInt();
			int m=sc.nextInt();
			BigInteger ans=BigInteger.valueOf(m);
			haha=BigInteger.valueOf(m);
			int i,j,k;
			for(i=1;i<=n;i++)
				a[i]=sc.nextInt();
			for(i=1;i<=n;)
			{
				for(j=i;j+1<=n;j++)
				{
					if(a[j+1]>a[j])//找最小值(a[j])
					{
						break;
					}
				}
				if(j==n) //此处不可省略!!!
	                	break;
				for(k=j+1;k+1<=n;k++)
				{
					if(a[k+1]<a[k])//找最大值(a[k])
					{
						break;
					}
				}
				BigInteger numm=haha.divide(BigInteger.valueOf(a[j]));//买的个数
				BigInteger lala=haha.subtract(numm.multiply(BigInteger.valueOf(a[j])));//买完后剩的钱
				  
				 haha=lala.add(numm.multiply(BigInteger.valueOf(a[k])));
				i=k+1;
			}
			System.out.println("Case #"+anaaa+": "+haha.mod(BigInteger.valueOf(1000000007)));
		}
	}

}

K:错排公式

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

代码:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int M = 1e9 + 7;
const int MAXN = 10009;
ll c[MAXN], d[MAXN], inv[MAXN];
int t, n, k;
void getC()
{
	c[0] = 1;
	for (int i = 0; i < n; ++i) {
		c[i + 1] = (((c[i] * (n - i)) % M) * inv[i + 1]) % M;
	}
}
int main()
{
	d[0] = 0;
	d[2] = 1;
	d[3] = 2;
	for (int i = 4; i <= 10001; ++i) {
		d[i] = 1LL * (i - 1) * (d[i - 1] + d[i - 2]) % M;
	}
	inv[1] = 1;
	for (ll i = 2; i <= 10001; ++i) {
		inv[i] = (M - M / i) * inv[M % i] % M;
	}
	scanf("%d", &t);
	while (t--) {
		scanf("%d %d", &n, &k);
		getC();
		ll ans = 1;
		for (int i = k; i < n; ++i) {
			ans = (ans + (c[i] * d[n - i]) % M) % M;
		}
		printf("%lld\n", ans);
	}
	return 0;
}
L:

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

两步赢得对手的步骤是:Kim下,对方下,Kim下。如果棋子能够三连就算Kim赢。

自己还没模拟。学长的代码先粘上。

代码:

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 100009;
char ch, chh;
struct Lu
{
	char mp[5][5];
} L, LL, LLL;
bool check(Lu p, char oo)
{
	for (int i = 1; i <= 3; ++i) {
		if (p.mp[i][1] == oo && p.mp[i][1] == p.mp[i][2] && p.mp[i][1] == p.mp[i][3]) return 1;
		if (p.mp[1][i] == oo && p.mp[1][i] == p.mp[2][i] && p.mp[1][i] == p.mp[3][i]) return 1;
	}
	if (p.mp[1][1] == oo && p.mp[1][1] == p.mp[2][2] && p.mp[1][1] == p.mp[3][3]) return 1;
	if (p.mp[1][3] == oo && p.mp[1][3] == p.mp[2][2] && p.mp[1][3] == p.mp[3][1]) return 1;
	return 0;
}
bool solve(Lu p)
{
	queue <Lu> qq;
	LLL = p;
	for (int i = 1; i <= 3; ++i) {
		for (int j = 1; j <= 3; ++j) {
			if (LLL.mp[i][j] == '.') {
				LLL.mp[i][j] = chh;
				if (check(LLL, chh)) return 0;
				qq.push(LLL);
				LLL.mp[i][j] = '.';
			}
		}
	}
	while (!qq.empty()) {
		LL = qq.front(); qq.pop();
		int tmp = 0;
		for (int i = 1; i <= 3; ++i) {
			for (int j = 1; j <= 3; ++j) {
				if (LL.mp[i][j] == '.') {
					LL.mp[i][j] = ch;
					if (check(LL, ch)) tmp = 1;
					LL.mp[i][j] = '.';
				}
			}
		}
		if (!tmp) return 0;
	}
	return 1;
}
bool bfs()
{
	queue <Lu> q;
	LL = L;
	for (int i = 1; i <= 3; ++i) {
		for (int j = 1; j <= 3; ++j) {
			if (LL.mp[i][j] == '.') {
				LL.mp[i][j] = ch;
				q.push(LL);
				LL.mp[i][j] = '.';
			}
		}
	}	
	while (!q.empty()) {
		L = q.front(); q.pop();
		if (solve(L)) return 1;
	}
	return 0;
}
int main()
{
	int t;
	scanf("%d", &t);
	while (t--) {
		for (int i = 1; i <= 3; ++i) {
			for (int j = 1; j <= 3; ++j) cin >> L.mp[i][j];
		}
		cin >> ch;
		if (ch == 'o') chh = 'x';
		else chh = 'o';
		if (check(L, ch)) puts("Kim win!");
		else if (check(L, chh)) puts("Cannot win!");
		else if (bfs()) puts("Kim win!");
		else puts("Cannot win!");
	}
	return 0;
}

ps:~~~~~好对不起学长,自己全程就是读题的,然后题还没读懂。怎么这么菜呢~还是只能A下水题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值