哈理工第九届程序设计竞赛

版权声明:转载请带一下我这个小蒟蒻哦~ https://blog.csdn.net/QLU_minoz/article/details/88934199
A.计算器
Time Limit: 1000 MS Memory Limit: 262144 K
Total Submit: 1348 (373 users) Total Accepted: 307 (302 users) Special Judge: No
Description
    给出一个形如“A+B”的式子,要求计算结果
Input
    多组数据,读入到文件结尾
    对于每一组数据,都是一行字符串
Output
    对于每组测试数据,输出对应的结果
Sample Input
    123+456
    2+4
Sample Output
    579
    6
Hint
    保证 A 和 B 都在 int 范围内且都是整数

貌似考察分离字符串数字的能力...emmmm一个sscanf就够了,不过因为A,B是int型,A+B就可能超过哦,一个小坑点

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+5;
int main()
{
    char a[maxn];
    ll x,y;
    while(cin>>a)
    {
        int flag=0;
        for(int i=0;;i++)
        {
            if(a[i]=='+')
            {
                flag=i;
                break;
            }
        }
        sscanf(a,"%lld%lld",&x,&y);
        printf("%lld\n",x+y);

    }
}
B.摆书
Time Limit: 1000 MS Memory Limit: 262144 K
Total Submit: 458 (196 users) Total Accepted: 121 (121 users) Special Judge: No
Description
    Quasrain 和 FZ 是好朋友。某天老师交给他们两组相同的书,每组书都是 n 本且不重复。他们需要把这两组书排列到一行 n 个书架上,每个书架上放两本书,且同一个人不能在同一个书架上放两本书。现在他们想知道,每个书架上的两本书都不一样的方案数。这n个书架互相等价,不区分顺序
Input
    多组数据,读入到文件结尾。
    对于每一组数据,包含一个数 n,意义如题面所示
Output
    对于每组数据,输出方案数,对 998244353 取模后的值
Sample Input
    2
    3
    4
Sample Output
    1
    2
    9
Hint
    2<=N<=10^5

    输入数据不超过 100 行

对于第二组样例:摆放方式有

    甲取{1,2,3},乙取{2,3,1}

    甲取{1,2,3},乙取{3,1,2}

甲取{1,2,3},乙取{2,3,1}的方案与甲取{2,1,3},乙取{3,2,1}的方案等价

错排典型例题...

公式f(n)=(n-1)*(f(n-1)+f(n-2))

不了解错排的戳这里https://blog.csdn.net/xiaohuan1991/article/details/6416047

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define Mod 998244353
const int maxn=1e5+5;

long long a[maxn];
void f()
{
    a[2]=1;
    a[3]=2;
    a[4]=9;
    for(int i=5;i<maxn;i++)
        a[i]=(a[i-1]%Mod*(i-1)%Mod+a[i-2]%Mod*(i-1)%Mod)%Mod;
}

int main()
{
    f();
    int n;
    while(~scanf("%d",&n))
    {
        printf("%d\n",a[n]);
    }
}
C.挖坑
Time Limit: 1000 MS Memory Limit: 262144 K
Total Submit: 409 (138 users) Total Accepted: 61 (60 users) Special Judge: No
Description
    Quasrain 和 FZ 是好朋友。Quasrain 善于挖坑而 FZ 善于填坑。
    这个游戏一共会持续 2N 天。在每一天都会有人挖坑或者填坑,并在本子上记录下“A”表示这天挖了坑,“B”表示填了坑。填坑必须填一个现存的还没有被填过的坑。
    作为素质优秀的熊孩子,他们保证在最后一天结束的时候一定会恰好填平所有坑。
    问本子上可能有多少种不同的 AB 序列
Input
    第一行一个数 T 表示数据组数(T<=100000)
    之后 T 行每行一个数 N,意义如题面所示(1<=N<=1000)
Output
    对于每组数据输出方案数,对 998244353 取模
Sample Input
    3
    1
    2
    3
Sample Output
    1
    2
    5
Hint
    对于第三组样例:
    可能的 AB 序列分别为:{AAABBB},{AABABB},{AABBAB},{ABAABB},{ABABAB}

     任意前缀中A的个数不少于B的个数,妥妥的卡特兰数,我用的是c(n)=c(n-1)*(4*n-2)/(n+!)   由于卡特兰数太大惹,我就用了java的BigInteger,然鹅java没有双倍实现悲催的TLE,于是就打了个表QAQ,

卡特兰数讲解https://blog.csdn.net/wu_tongtong/article/details/78161211

java的卡特兰数打表

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


public class hdu1042 {
    static BigInteger a[] = new BigInteger[10000+5]; 
    static BigInteger b = new BigInteger("998244353"); 
    
    static Scanner cin = new Scanner(System.in);
    
    public static void f() {
		a[1] = new BigInteger("1");
		for(int i=2;i<=1005;i++) {
				a[i]=(a[i-1].multiply(new BigInteger(String.valueOf(4*i-2))).divide(new BigInteger(String.valueOf(i+1))));
		}
    }
    
	public static void main(String[] args) {
//		int t=cin.nextInt();
//		int tt=0;
		f();
		for(int i=1;i<=1005;i++)
		{
			System.out.println(a[i].remainder(b));
			System.out.println(",");
		}
//		while(tt<t) {
//		    int n=cin.nextInt();
//			System.out.println(a[n]);
//			tt++;
//		}
	}
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
int c[1000+5]={表.....};//为了不污染视线,表就不上了
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        printf("%d\n",c[n-1]);
    }
    return 0;
}

1,2,5,14,42,132,429,1430,4862,16796,58786,208012,742900,2674440,9694845,35357670,129644790,477638700,769018837,574654302,508402548(表的前几位)

E.复读机
Time Limit: 1000 MS Memory Limit: 262144 K
Total Submit: 928 (326 users) Total Accepted: 284 (281 users) Special Judge: No
Description
    人类的本质是复读机,当然也包括 Quasrain 和 FZ “+1”按钮当且仅当在至少两次同样的字符串之后可以被点击。
    所有可以点击“+1”按钮的时候 FZ 都会点击,但 FZ 不喜欢复读自己。
    比如出现连续三个字符串”aaa”,”aaa”,”aaa”时,他只会在第二次出现”aaa”时点击一次”+1”按钮
    现在给出 n 个字符串表示当天的聊天记录,出于研究目的,Quasrain 想要知道 FZ 一天里需要点击多少次”+1”按钮。
Input
    第一行一个正整数 T,表示数据组数(T<=5)
    对于每组数据:第一行一个正整数 n 表示今日的聊天记录条数(n<=1000)
    接下来 n 行每行一个字符串,保证字符串长度<=1000,且仅会出现大小写字母和数字
Output
    对于每组测试数据,输出一行一个整数表示答案
Sample Input
    1
    6
    111
    111
    22
    111
    111
    111
Sample Output
    2
Hint
    点击分别在第 2 行和第 5 行
E.复读机
Time Limit: 1000 MS Memory Limit: 262144 K
Total Submit: 928 (326 users) Total Accepted: 284 (281 users) Special Judge: No
Description
    人类的本质是复读机,当然也包括 Quasrain 和 FZ “+1”按钮当且仅当在至少两次同样的字符串之后可以被点击。
    所有可以点击“+1”按钮的时候 FZ 都会点击,但 FZ 不喜欢复读自己。
    比如出现连续三个字符串”aaa”,”aaa”,”aaa”时,他只会在第二次出现”aaa”时点击一次”+1”按钮
    现在给出 n 个字符串表示当天的聊天记录,出于研究目的,Quasrain 想要知道 FZ 一天里需要点击多少次”+1”按钮。
Input
    第一行一个正整数 T,表示数据组数(T<=5)
    对于每组数据:第一行一个正整数 n 表示今日的聊天记录条数(n<=1000)
    接下来 n 行每行一个字符串,保证字符串长度<=1000,且仅会出现大小写字母和数字
Output
    对于每组测试数据,输出一行一个整数表示答案
Sample Input
    1
    6
    111
    111
    22
    111
    111
    111
Sample Output
    2
Hint
    点击分别在第 2 行和第 5 行

这个题,貌似题意不是很明确,所以造成了理解坑点...我开始想的是A说的话他复读了,然后B也复读了,他也可以复读B说的话呢...结果交了一发WA,然后才知道的一个复读区间段只能复读一次...

K.选数 II
Time Limit: 1000 MS Memory Limit: 2048 K
Total Submit: 1045 (312 users) Total Accepted: 239 (235 users) Special Judge: No
Description
    有一行 n 个数,其中所有数都恰好出现了两次,除了两个特殊的数只出现了一次。现在 Quasrain 想知道这两个特殊的数分别是多少
Input
    多组数据。
    第一行一个整数 T 表示数据组数(T<=5)
    对于每组数据,第一行一个整数 n,意义如题面所示(保证 n 为偶数,n<=100000)
    接下来一行 n 个正整数 Ai。(0<=Ai<2^31-1)
Output
    对于每组数据,输出一行两个正整数,表示两个特殊的数,按小的在前大的在后的顺序输出
Sample Input
    2
    4
    2 2 3 4
    6
    1 2 3 2 3 5
Sample Output
    3 4
    1 5
Hint
    请使用高效的读入方式

其实这个题是一个题的拓展,原题是有一行 n 个数,其中所有数都恰好出现了两次,除了一个特殊的数只出现了一次。求这个特殊的数是多少

由于a^a=0,也就a^b^a=b,所以,全部的数异或起来,所得的结果就是这个特殊的数。

这里是两个特殊的数,其实整体思路也是这样。

把全部的数异或起来,根据上面知道,结果是两个特殊的数的异或sum。然后算出sum的二进制第一个1的位置flag,再将所有数根据二进制flag位置是否为1分成两组b1[],b2[] ,将b1组异或得到ans1,将b2组异或得到ans2

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        int sum=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            sum^=a[i];
        }
        cout<<sum<<endl;
        int flag=0;
        while(!((sum>>flag)&1))
            flag++;//sum的二进制第一个1的位置flag
        flag=1<<flag;
        int ans1=0,ans2=0;
        for(int i=0;i<n;i++)
        {
            if(flag&a[i])//二进制flag位置为1
                ans1^=a[i];
            else
                ans2^=a[i];
        }
        printf("%d %d\n",min(ans1,ans2),max(ans1,ans2));
    }
}

猜你喜欢

转载自blog.csdn.net/QLU_minoz/article/details/88934199
今日推荐