“蔚来杯“2022牛客暑期多校训练营8 题解

F题 Longest Common Subsequence
思路:通过一个函数公式x->(axx+b*x+c)%p构造s和t数组,问s和t的最长公共子序列有多长。如果x相同的话,那后面的所有存在元素都一定相同,但是x不同的话,也有可能通过%p使得后一个数相同。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e6+5;
ll p,x,a,b,c;
ll s[2000006];
int t,n,m; 
unordered_map<ll,ll> mp;
ll qk(ll a,ll b){
	ll ans=1;
	a%=p;
	b%=p;
	while(b){
		if(b&1) ans=ans*a%p;
		a=a*a%p;
		b>>=1;
	}
	return ans; 
}
int main(){
    scanf("%d",&t);
    while(t--){
        mp.clear();
        scanf("%d%d",&n,&m);
        scanf("%lld%lld%lld%lld%lld",&p,&x,&a,&b,&c);
        s[0]=x;
        for(ll i=1;i<=n;i++){//构造s数组
            s[i]=((s[i-1]*a%p*s[i-1]%p+b*s[i-1]%p)%p+c%p)%p;
            if(mp[s[i]]==0) mp[s[i]]=i;//记录每个元素出现的最开始的位置
        }
        ll ans=0;
        for(ll i=n+1;i<=m+n;i++){//构造t数组
            s[i]=((s[i-1]*a%p*s[i-1]%p+b*s[i-1]%p)%p+c%p)%p;
            if(mp[s[i]]<0) break;
            if(mp[s[i]]>0) {//找出相同序列最长的序列长度
                ans=max(ans,min(n-mp[s[i]]+1,m+n-i+1));
                mp[s[i]]=-1;      
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

D题 Poker Game
思路:一共有十种类型的牌型,模拟AB拿到牌的可能性,由此判断AB必胜或者平局的情况。

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
typedef unsigned long long ull;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
unordered_map<char, int> rk;
struct node{
    int rank, col;
    bool operator<(const node r) const{
        return rank > r.rank;
    }
} A[10], B[10], C[10], tmp[2][10];
bool mark[10];
int cnt[20];
 
void init(){
    int cnt = 0;
    for (auto i : "123456789TJQKA")
        rk[i] = ++cnt;
    cnt = 0;
    for (auto i : "SHCD")
        rk[i] = ++cnt;
}
 
int getrank(int p){
    for (int i = 1; i <= 15; i++)
        cnt[i] = 0;
    for (int i = 1; i <= 5; i++){
        cnt[tmp[p][i].rank]++;
        if (tmp[p][i].rank == 14)
            cnt[1]++;
    }
    bool flag = 1; //判断同花
    for (int i = 2; i <= 5; i++)
        if (tmp[p][i].col != tmp[p][i - 1].col)
            flag = 0;
    bool sh = 0; //判断顺子
    for (int i = 14; i >= 5; i--){
        bool shun = 1;
        for (int j = i; j >= i - 4; j--)
            if (cnt[j] == 0)
                shun = 0;
        if (shun)
            sh = 1;
    }
    if (sh && cnt[1] > 0 && cnt[2] > 0)
        for (int i = 1; i <= 5; i++)
            tmp[p][i].rank = 5 - i + 1;
    if (flag && sh)
        return 9; //同花顺
    for (int i = 14; i >= 2; i--)
        if (cnt[i] == 4){ //炸
            for (int j = 1; j <= 4; j++)
                tmp[p][j].rank = i;
            for (int j = 14; j >= 2; j--)
                if (cnt[j] == 1)
                    tmp[p][5].rank = j;
            return 8;
        }
    for (int i = 14; i >= 2; i--)
        if (cnt[i] == 3) //三带二
            for (int j = 14; j >= 2; j--)
                if (cnt[j] == 2){
                    for (int k = 1; k <= 3; k++)
                        tmp[p][k].rank = i;
                    for (int k = 4; k <= 5; k++)
                        tmp[p][k].rank = j;
                    return 7;
                }
    if (flag)
        return 6; //同花
    if (sh)
        return 5; //顺子
    for (int i = 14; i >= 2; i--)
        if (cnt[i] == 3) { //三带一
            for (int j = 1; j <= 3; j++)
                tmp[p][j].rank = i;
            int k = 4;
            for (int j = 14; j >= 2; j--)
                if (cnt[j] == 1)
                    tmp[p][k++].rank = j;
            return 4;
        }
    int sum = 0, k = 1;
    for (int i = 14; i >= 2; i--)
        if (cnt[i] == 2){
            sum++;
            tmp[p][k++].rank = i;
            tmp[p][k++].rank = i;
        }
    if (sum > 0)
        for (int i = 14; i >= 2; i--)
            if (cnt[i] == 1)
                tmp[p][k++].rank = i;
    if (sum == 2)
        return 3; //两对对子
    else if (sum == 1)
        return 2; //对子
    else
        return 1;
}
int compare() //同tpye下比rank,返回-1Alice赢,返回0平手
{
    for (int i = 1; i <= 5; i++)
        if (tmp[0][i].rank > tmp[1][i].rank)
            return -1;
        else if (tmp[0][i].rank < tmp[1][i].rank)
            return 1;
    return 0;
}
int dfs(int x, int y, int p){
    if (x == 4 && y == 4){
        for (int i = 1; i <= 5; i++){
            tmp[0][i] = A[i];
            tmp[1][i] = B[i];
        }
        sort(tmp[0] + 1, tmp[0] + 6);
        sort(tmp[1] + 1, tmp[1] + 6);
        int a = getrank(0), b = getrank(1);
        if (a != b){
            if (a > b)
                return -1;
            else
                return 1;
        }
        else
            return compare();
    }
    bool flag = 0;
    for (int i = 1; i <= 6; i++){
        if (mark[i])
            continue;
        mark[i] = 1;
        int res;
        if (p == 0){
            A[2 + x] = C[i];
            res = dfs(x + 1, y, 1);
        }
        else{
            B[2 + y] = C[i];
            res = dfs(x, y + 1, 0);
        }
        mark[i] = 0;
        if (res == 1)
            return -1;
        else if (res == 0)
            flag = 1;
    }
    return flag ? 0 : 1;
}
node read(){
    char c1, c2;
    cin >> c1 >> c2;
    return {rk[c1], rk[c2]};
}
void run()
{
    memset(mark, 0, sizeof(mark));
    A[1] = read();
    A[2] = read();
    B[1] = read();
    B[2] = read();
    for (int i = 1; i <= 6; i++)
        C[i] = read();
    int res = dfs(1, 1, 0);
    if (res == -1)
        cout << "Alice";
    else if (res == 0)
        cout << "Draw";
    else
        cout << "Bob";
    cout << endl;
}
signed main()
{
    int T = 1;
 
    init();
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    cin >> T;
    while (T--)
        run();
 
    return 0;
}

相关文章

学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习...
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面...
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生...
Can’t connect to local MySQL server through socket \'/v...
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 ...
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服...