2022-03-02每日刷题打卡

2022-03-02每日刷题打卡

代码源——div2每日一题

Alice的德州扑克 - 题目 - Daimayuan Online Judge

德州扑克是目前世界上最流行的扑克游戏,全世界有众多相关的比赛,例如是 WSOP,WPT,EPT等,也让这款游戏的玩法变得层出不穷,丰富多变。 不要被简单的游戏规则而误导,复杂多变的比赛状况,让这款游戏在高水平的竞技中会变得非常复杂,这也让人们为德州扑克给出了这样一句评价 ”用一刻就能学会,但要用一生才能掌握” 。

现在我们并不在乎游戏规则是什么,因为 Alice 是一个德州扑克高手,他对于德州扑克的规则烂熟于心,不过他每次都记不得牌型的大小关系,他知道你是一个编程高手,所以他想让你帮他写一个程序:输入五张牌的大小和花色,输出这五张牌能组成的最大牌型.你能帮帮他吗?

为了降低你的编程难度,我们规定:

  1. 输入的牌都是来源于同一副扑克牌.
  2. 输入的牌的点数都是非递减的.
  3. 所有花色没有大小之分.

下面给出各牌型,(从大到小)

  1. 皇家同花顺(ROYAL FLUSH):五张顺连的牌(点数连续单调递增),且最大的一张牌是A(Ace),并且五张牌的花色相同
  2. 同花顺(STRAIGHT FLUSH):五张顺连的牌(点数连续单调递增),不规定最大的一张牌是A(Ace),并且五张牌的花色相同
  3. 四条(FOUR OF A KIND):至少四张牌的点数相同
  4. 葫芦(FULL HOUSE):至少三张牌的点数相同,并且除此之外还有两张牌的点数相同
  5. 同花(FLUSH):五张牌的花色都相同
  6. 顺子(STRAIGHT):五张顺连的牌(点数连续单调递增),不要求五张牌的花色相同
  7. 特别注意:由于 Alice 是个谨慎的人,所以比 三条(THREE OF A KIND) (包括三条) 小的牌型 Alice 不在乎他们的大小关系,你只需要告诉 Alice 弃牌就行
输入格式

输入两行,每行五个数字,第一行的第 ii 个字符表示第 ii 张扑克的点数,

第二行的第 ii 个数字表示第 ii 张扑克花色。(保证输入的牌的点数是非递减的,且所有输入均合法)

点数和对应输入的数字:

  • 2−102−10 对应 2 - 10
  • J(Jack)J(Jack) 对应 11
  • Q(Queen)Q(Queen) 对应 12
  • K(King)K(King) 对应 13
  • A(Ace)A(Ace) 对应 14

花色和对应输入的数字:

  • 黑桃 (Spades) 对应 1
  • 方片 (Diamonds) 对应 2
  • 红桃 (Hearts) 对应 3
  • 梅花 (Clubs) 对应 4
输出格式

输出这五张牌能组成的最大牌型.

  • 如果最大是皇家同花顺输出 “ROYAL FLUSH”
  • 如果最大是同花顺输出 “STRAIGHT FLUSH”
  • 如果最大是四条输出 “FOUR OF A KIND”
  • 如果最大是葫芦输出 “FULL HOUSE”
  • 如果最大是同花输出 “FLUSH”
  • 如果最大是顺子输出 “STRAIGHT”
  • 如果最大的牌型小于等于三条输出"FOLD",劝 Alice 弃牌
  • 输出不包括引号
样例输入1
10 11 12 13 14
1 1 1 1 1
样例输出1
ROYAL FLUSH

模拟题嗷模拟题,没啥特别的知识

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>

typedef long long ll;
const int N = 100005;

int main()
{
	bool two = false, three = false, four = false, flush = true, straight = true, A = false;
	int ans;
	map<int, int>mymap;
	for (int i = 0; i < 5; i++)
	{
		int num;
		cin >> num;
		if (i == 0)ans = num;
		else if (ans + 1 != num)
		{
			straight = false;
		}
		else ans = num;
		mymap[num]++;
		if (i == 4 && num == 14)A = true;
	}
	for (auto i : mymap)
		if (i.second == 2)two = true;
		else if (i.second == 3)three = true;
		else if (i.second == 4)four = true;
	for (int i = 0; i < 5; i++)
	{
		int flu;
		cin >> flu;
		if (i == 0)ans = flu;
		else if (ans != flu)flush = false;
	}

	if (flush && straight && A)cout << "ROYAL FLUSH" << endl;
	else if (flush && straight)cout << "STRAIGHT FLUSH" << endl;
	else if (four)cout << "FOUR OF A KIND" << endl;
	else if (two && three)cout << "FULL HOUSE" << endl;
	else if (flush)cout << "FLUSH" << endl;
	else if (straight)cout << "STRAIGHT" << endl;
	else cout << "FOLD" << endl;

	return 0;
}
选数 - 题目 - Daimayuan Online Judge

给定n个正整数a1,a2,…,an 。 要求从其中选出若干数字, 使得这些数字的和mod n=0(对于每个下标最多只能选择一次)。

输入格式

第一行一个数字n, 表示数字个数。

接下来一行 n 个整数 a1,a2,…,an , 表示这n个数。

输出格式

第一行输出MM, 表示选择的数的个数。

第二行输出MM个正整数, 用空格隔开, 表示这些数字的下标。

如果有多种方案满足要求, 输出任意一种。

如果没有满足要求的方案 输出 −1−1。

样例输入
4
1 3 2 5
样例输出
2
2 4
样例解释

3+5=8, 8 mod 4=0

数据规模

所有数据保证 1≤n≤100000,1≤ai≤10^9

这题用前缀和的思路来解。准备一个前缀和数组f,f[i]记录的是前i个元素的和,再%n。如果f[i]等于0,那就,满足题目要求,直接输出前i个元素即可。如果算完前缀和后,整个数组里都没有等于0的情况,此时就要用到抽屉问题了。首先我们知道,我们是对n取模,这样得到的数范围应该是0n-1,此时我们得到的数里没有0,那么范围就是1n-1,一共是n-2个数,但我们通过计算前缀和得到的元素个数应该是n,但此时所有元素的数据范围是1~n-1,这就说明了,至少有两个数会相等,既然相等,这两数的差值就是0,这就说明这两个数中间隔着的数,总和%n后等于0,所以这两个数之间相隔的数是满足条件的,输出即可。

例如:1 2 3 5这四个元素,计算前缀和并%4后得到的是1 3 2 3,相同的是第2个元素和第4个元素,那满足条件的就是第三到第四给元素,即3 和 5,3+5=8%4=0。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>

typedef long long ll;
const int N = 100005;
ll f[N];

int main()
{
	unordered_map<ll, vector<int>>mymap;
	int n, ans = -1, res = 0;
	cin >> n;
	vector<ll>v(n+1);
	for (int i = 1; i <= n; i++)
	{
		cin >> v[i], f[i] = (f[i - 1] + v[i]) % n;
		if (f[i] == 0)ans = i;
		mymap[f[i]].push_back(i);
		if (mymap[f[i]].size() >= 2)res = f[i];
	}
	if (ans != -1)
	{
		cout << ans << endl;
		for (int i = 1; i <= ans; i++)cout << i << " ";
		return 0;
	}
	int a = mymap[res][0], b = mymap[res][1];
	cout << b - a  << endl;
	for (int i = a + 1; i <= b; i++)
		cout << i << " ";
	

	return 0;
}

力扣——每日一题

564. 寻找最近的回文数

给定一个表示整数的字符串 n ,返回与它最近的回文整数(不包括自身)。如果不止一个,返回较小的那个。

“最近的”定义为两个整数差的绝对值最小。

示例 1:

输入: n = “123”
输出: “121”

提示:

  • 1 <= n.length <= 18
  • n 只由数字组成
  • n 不含前导 0
  • n 代表在 [1, 1018 - 1] 范围内的整数

有五种方式来构造回文整数:

1是取前一半的数镜像填到后面去,例:12345,把前面的123填到后面就是12321。

2是取前一半的数,+1后填到后面去,例:12345,把123+1后变成124,再填就是12421。

3是取前一半的数,-1后填到后面去,例:12345,123-1后是122,再填就是12221。

4是取上限,因为我们把中间数+1后(第二种方法)有可能会使数位加1,比如9999,会变成100001,但实际应该是10001,我们提前准备一个上限的数,取数的长度len,根据len构造一个10的len次方的数,再+1。比如9999长度是4,那就是10^4+1=10001。

5是取下线,我们把中间数-1后(第三种方法)有可能会使数位减一,比如1001,会变成99,但实际是999,我们提前准备一个下限的数,取数的长度len,根据len构造一个10的len-1次方的数,再-1。比如1001长度是4,那就是10^3-1=999。

最后我们依次拿这五个数和n进行比较,取之间差值最小的那一个,如果差值相同,取数较小的那一个,注意这五个数不能有和n相同的,而且根据题目的范围,我们全程的数应该开longlong。

class Solution {
public:
    typedef long long ll;
    ll get_back(string str,int ans,int len)
    {
        int n=len%2==0?len/2:len/2+1;
        string s=str.substr(0,n);
        ll num=stol(s);
        num+=ans;
        str=to_string(num);
        n=str.size();
        if(len%2)n--;
        for(int i=n-1;i>=0;i--)str+=str[i];
        return stol(str);
    }
    string nearestPalindromic(string n) {
        vector<ll>v;
        int len=n.size();
        v.push_back(pow(10,len)+1);
        v.push_back(pow(10,len-1)-1);
        v.push_back(get_back(n,1,len));
        v.push_back(get_back(n,0,len));
        v.push_back(get_back(n,-1,len));

        ll res=1e18,num=stol(n),ans=1e18;
        for(int i=0;i<5;i++)
        {
            ll val=abs(v[i]-num);
            if(res>=val&&v[i]!=num)
            {
                if(res==val) ans=min(ans,v[i]);
                else ans=v[i];
                res=val;
            }
        }
        return to_string(ans);
    }
};

一本通——动态规划

1297:公共子序列

【题目描述】

我们称序列Z=<z1,z2,…,zk>是序列X=<x1,x2,…,xm>的子序列当且仅当存在严格上升的序列<i1,i2,…,ik>,使得对j=1,2,…,k,有xij=zj。比如Z=<a,b,f,c> 是X=<a,b,c,f,b,c>的子序列。

现在给出两个序列X和Y,你的任务是找到X和Y的最大公共子序列,也就是说要找到一个最长的序列Z,使得Z既是X的子序列也是Y的子序列。

【输入】

输入包括多组测试数据。每组数据包括一行,给出两个长度不超过200的字符串,表示两个序列。两个字符串之间由若干个空格隔开。

【输出】

对每组输入数据,输出一行,给出两个序列的最大公共子序列的长度。

【输入样例】

abcfbc abfcab
programming contest  
abcd mnp
【输出样例】
4 
2 
0
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>

typedef long long ll;
const int N = 1005;
int f[N][N];

int main()
{
	string str1, str2;
	while (cin >> str1 >> str2)
	{
		int n = str1.size(), m = str2.size(), res = 0;
		for(int i=1;i<=n;i++)
			for (int j = 1; j <= m; j++)
			{
				if (str1[i - 1] == str2[j - 1])
					f[i][j] = f[i - 1][j - 1] + 1;
				else
					f[i][j] = max(f[i][j - 1], f[i - 1][j]);
				res = max(f[i][j], res);
			}
		cout << res << endl;
	}
	return 0;
}
1298:计算字符串距离

【题目描述】

对于两个不同的字符串,我们有一套操作方法来把他们变得相同,具体方法为:

修改一个字符(如把“a”替换为“b”);

删除一个字符(如把“traveling”变为“travelng”)。

比如对于“abcdefg”和“abcdef”两个字符串来说,我们认为可以通过增加/减少一个“g”的方式来达到目的。无论增加还是减少“g”,我们都仅仅需要一次操作。我们把这个操作所需要的次数定义为两个字符串的距离。

给定任意两个字符串,写出一个算法来计算出他们的距离。

【输入】

第一行有一个整数n。表示测试数据的组数。

接下来共n行,每行两个字符串,用空格隔开,表示要计算距离的两个字符串。

字符串长度不超过1000。

【输出】

针对每一组测试数据输出一个整数,值为两个字符串的距离。

【输入样例】

3 
abcdefg  abcdef
ab ab 
mnklj jlknm
【输出样例】
1 
0 
4
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>

typedef long long ll;
const int N = 1005;
int f[N][N];

int main()
{
	int len;
	cin >> len;
	string str1, str2;
	while (len--)
	{
		cin >> str1 >> str2;
		int n = str1.size(), m = str2.size(), res = 0;
		for (int i = 0; i <= n; i++)f[i][0] = i;
		for (int i = 0; i <= m; i++)f[0][i] = i;
		for(int i=1;i<=n;i++)
			for (int j = 1; j <= m; j++)
			{
				f[i][j] = min(f[i - 1][j], f[i][j - 1]) + 1;
				f[i][j] = min(f[i][j], str1[i - 1] == str2[j - 1] ? f[i - 1][j - 1] : f[i - 1][j - 1] + 1);
			}
		cout << f[n][m] << endl;
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值