AcWing - 337 - 扑克牌 = dp + 组合数学

https://www.acwing.com/problem/content/description/339/

感觉非常沙雕的一个东西。

首先设状态的时候要按张数来设,这样空间复杂度比较小。因为本身就和花色和面值没有什么关系的。

然后在预处理的时候就直接考虑花色的影响,就是乘上一个排列数。

记得要容斥一下,不然答案很有问题。

不知道为什么我的unsigned long long用不了(原因是因为减法a-1>=0溢出了),只好搞个__int128来表示模数,真是麻烦。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 ull;

ull dp[20][20][20][20] = {};
ull TWO = 2, THREE = 3, FOUR = 4, SIX = 6, MOD = 1;

const ull CEIL = 13;
string s;

ull mut(ull a, ull b) {
    ull res = 0;
    while(b) {
        if(b & 1)
            res = (res + a) % MOD;
        a = (a + a) % MOD;
        b >>= 1;
    }
    return res;
}

void init() {
    MOD <<= 64;
    for(ull d = 0; d <= CEIL; ++d) {
        for(ull c = 0; c <= CEIL; ++c) {
            for(ull b = 0; b <= CEIL; ++b) {
                for(ull a = 0; a <= CEIL; ++a) {
                    if(a == 0 && b == 0 && c == 0 && d == 0) {
                        dp[0][0][0][0] = 1llu;
                        continue;
                    }
                    if(a - 1 >= 0)
                        dp[a][b][c][d] += mut(dp[a - 1][b][c][d], a);
                    if(b - 1 >= 0) {
                        dp[a][b][c][d] += mut(mut(dp[a + 1][b - 1][c][d], TWO), b);
                        dp[a][b][c][d] -=  mut(mut(dp[a][b - 1][c][d], TWO), b);
                    }
                    if(c - 1 >= 0) {
                        dp[a][b][c][d] += mut(mut(dp[a][b + 1][c - 1][d], THREE), c);
                        dp[a][b][c][d] -= mut(mut(mut(dp[a + 1][b][c - 1][d], THREE), TWO), c);
                        dp[a][b][c][d] += mut(mut(mut(dp[a][b][c - 1][d], THREE), TWO), c);
                    }
                    if(d - 1 >= 0) {
                        dp[a][b][c][d] += mut(mut(dp[a][b][c + 1][d - 1], FOUR), d);
                        dp[a][b][c][d] -= mut(mut(mut(dp[a][b + 1][c][d - 1], FOUR), THREE), d);
                        dp[a][b][c][d] += mut(mut(mut(mut(dp[a + 1][b][c][d - 1], FOUR), THREE), TWO), d);
                        dp[a][b][c][d] -= mut(mut(mut(mut(dp[a][b][c][d - 1], FOUR), THREE), TWO), d);
                    }
                    dp[a][b][c][d] = (dp[a][b][c][d] % MOD + MOD) % MOD;
                }
            }
        }
    }

}

void write(ull ans) {
    if(ans >= 10) {
        write(ans / 10);
    }
    putchar(ans % 10 + '0');
}

int cnt[14] = {};
int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku

    init();
    int t;
    cin >> t;
    for(int ti = 1; ti <= t; ++ti) {
        int n;
        cin >> n;
        memset(cnt, 0, sizeof(cnt));
        for(int i = 1; i <= n; ++i) {
            cin >> s;
            if(s[0] == 'T') {
                cnt[10]++;
            } else if(s[0] == 'A') {
                cnt[1]++;
            } else if(s[0] == 'J') {
                cnt[11]++;
            } else if(s[0] == 'Q') {
                cnt[12]++;
            } else if(s[0] == 'K') {
                cnt[13]++;
            } else {
                cnt[s[0] - '0']++;
            }
        }
        ull cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0;
        for(int i = 1; i <= 13; ++i) {
            if(cnt[i] == 1)
                cnt1++;
            else if(cnt[i] == 2)
                cnt2++;
            else if(cnt[i] == 3)
                cnt3++;
            else if(cnt[i] == 4)
                cnt4++;
        }
        ull tmp = dp[cnt1][cnt2][cnt3][cnt4];
        cout << "Case #" << ti << ": ";
        write(tmp);
        cout << "\n";
    }
}

所以就印证了一句话,没事就不需要用unsigned,不然出事。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

ull dp[20][20][20][20] = {};

ull TWO = 2, THREE = 3, FOUR = 4, SIX = 6;

const int CEIL = 13;
string s;

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    for(int d = 0; d <= CEIL; ++d) {
        for(int c = 0; c <= CEIL; ++c) {
            for(int b = 0; b <= CEIL; ++b) {
                for(int a = 0; a <= CEIL; ++a) {
                    if(a == 0 && b == 0 && c == 0 && d == 0) {
                        dp[0][0][0][0] = 1llu;
                        continue;
                    }
                    if(a - 1 >= 0)
                        dp[a][b][c][d] += dp[a - 1][b][c][d] * a;
                    if(b - 1 >= 0) {
                        dp[a][b][c][d] += dp[a + 1][b - 1][c][d] * TWO * b;
                        dp[a][b][c][d] -= dp[a][b - 1][c][d] * TWO * b;
                    }
                    if(c - 1 >= 0) {
                        dp[a][b][c][d] += dp[a][b + 1][c - 1][d] * THREE * c;
                        dp[a][b][c][d] -= dp[a + 1][b][c - 1][d] * THREE * TWO * c;
                        dp[a][b][c][d] += dp[a][b][c - 1][d] * THREE * TWO * c;
                    }
                    if(d - 1 >= 0) {
                        dp[a][b][c][d] += dp[a][b][c + 1][d - 1] * FOUR * d;
                        dp[a][b][c][d] -= dp[a][b + 1][c][d - 1] * FOUR * THREE * d;
                        dp[a][b][c][d] += dp[a + 1][b][c][d - 1] * FOUR * THREE * TWO * d;
                        dp[a][b][c][d] -= dp[a][b][c][d - 1] * FOUR * THREE * TWO * d;
                    }
                }
            }
        }
    }
    int t;
    scanf("%d", &t);
    for(int ti = 1; ti <= t; ++ti) {
        int n;
        scanf("%d", &n);

        int cnt[14] = {};
        for(int i = 1; i <= n; ++i) {
            cin >> s;
            if(s[0] == 'T') {
                cnt[10]++;
            } else if(s[0] == 'A') {
                cnt[1]++;
            } else if(s[0] == 'J') {
                cnt[11]++;
            } else if(s[0] == 'Q') {
                cnt[12]++;
            } else if(s[0] == 'K') {
                cnt[13]++;
            } else {
                cnt[s[0] - '0']++;
            }
        }
        ull cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0;
        for(int i = 1; i <= 13; ++i) {
            if(cnt[i] == 1)
                cnt1++;
            else if(cnt[i] == 2)
                cnt2++;
            else if(cnt[i] == 3)
                cnt3++;
            else if(cnt[i] == 4)
                cnt4++;
        }
        ull tmp = dp[cnt1][cnt2][cnt3][cnt4];
        printf("Case #%d: %llu\n", ti, tmp);
    }
}

转载于:https://www.cnblogs.com/Inko/p/11605459.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
很抱歉,我是一个文本AI助手,无法提供PDF文件。不过,我可以为您提供一份基于C语言的21点扑克牌游戏代码供参考: ``` #include <stdio.h> #include <stdlib.h> #include <time.h> #define NUM_CARDS 52 #define FACE_CARD 10 #define ACE 11 int get_card_value(int card); void shuffle_deck(int deck[]); void deal_cards(int deck[], int *card1, int *card2); int player_turn(int deck[], int player_total); int dealer_turn(int deck[], int dealer_total); int main() { int deck[NUM_CARDS], player_total, dealer_total, card1, card2; srand((unsigned) time(NULL)); shuffle_deck(deck); deal_cards(deck, &card1, &card2); player_total = get_card_value(card1) + get_card_value(card2); printf("You have a %d and a %d.\n", card1, card2); printf("Your total is %d.\n\n", player_total); dealer_total = dealer_turn(deck, get_card_value(deck[2])); if (dealer_total > 21 || dealer_total < player_total) { printf("You win!\n"); } else { printf("Dealer wins!\n"); } return 0; } int get_card_value(int card) { int value; if (card > FACE_CARD) { value = FACE_CARD; } else if (card == 1) { value = ACE; } else { value = card; } return value; } void shuffle_deck(int deck[]) { int i, j, temp; for (i = 0; i < NUM_CARDS; i++) { deck[i] = i + 1; } for (i = 0; i < NUM_CARDS; i++) { j = rand() % NUM_CARDS; temp = deck[i]; deck[i] = deck[j]; deck[j] = temp; } } void deal_cards(int deck[], int *card1, int *card2) { *card1 = deck[0]; *card2 = deck[1]; } int player_turn(int deck[], int player_total) { int card, value; char hit; while (player_total < 21) { printf("Do you want another card? (y/n) "); scanf(" %c", &hit); if (hit == 'n') { break; } card = deck[NUM_CARDS - 1]; value = get_card_value(card); printf("You drew a %d.\n", card); player_total += value; if (player_total > 21) { printf("You busted!\n"); break; } printf("Your total is %d.\n\n", player_total); } return player_total; } int dealer_turn(int deck[], int dealer_total) { int card, value; printf("The dealer's hole card is a %d.\n", deck[1]); while (dealer_total < 17) { card = deck[NUM_CARDS - 1]; value = get_card_value(card); printf("The dealer drew a %d.\n", card); dealer_total += value; if (dealer_total > 21) { printf("Dealer busted!\n"); break; } printf("Dealer's total is %d.\n\n", dealer_total); } return dealer_total; } ``` 这个代码使用一个数组来表示一副扑克牌,通过随机洗牌函数来打乱这副牌的顺序。然后,根据游戏规则,玩家和庄家各发两张牌,然后根据牌的点数来进行游戏。当玩家的点数小于或等于21并且没有爆牌时,可以选择继续要牌或者不要牌。当玩家停止要牌后,庄家也进行类似的操作。最后,比较玩家和庄家的点数,判断胜负。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值