PTA 520 钻石争霸赛

本博客只含比赛的最后三题

7-6 随机输一次 (20分)

在这里插入图片描述
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int n;cin >> n;
	vector<int> v;
	int a;
	for(int i = 0; i < n; i++)
	{
		cin >> a;
		v.push_back(a);
	}
	map<string, string> ying = {   // 三种手势对应赢的招数
		{"ChuiZi", "Bu"},
		{"JianDao", "ChuiZi"},
		{"Bu", "JianDao"}
	},
		shu = {   // 三种手势对应输的招数
		{"Bu", "ChuiZi"},
		{"ChuiZi", "JianDao"},
		{"JianDao", "Bu"}
	};
	int current = 0, end = 0;
	while(1)
	{
		// 赢若干次
		for(int j = 0; j < v[current % n]; j++)
		{
			string x;
			cin >> x;
			if(x == "End")
			{
				end = 1;   // "End"代表输入结束,设置标志并退出循环
				break;
			}
			cout<<ying[x]<<endl;
		}
		if(end) break;
		
		// 输一次
		string x;
		cin >> x;
		if(x == "End")
			break;
		cout<<shu[x]<<endl;
		current++;   // 换下一组随机数
	}
	return 0;
}

如果对方出招太多,则随机数按顺序循环使用,所以是 v [current % n]

7-7 阶乘的非零尾数 (20分)

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //加快 cin 与 cout的速度 
    int n,k;
    cin>>n>>k; // N 阶乘末尾的第一个非零 k 位数
    int base=pow(10,k); //对 k位数 取模 
    int t=n; // 找个替代,防止 n 改变 
    int ans=0; // N 阶乘末尾的 0 的个数 
    while(t) //用于求 N 阶乘末尾的 0 的个数的方法(不懂的话硬记着就好) 
	{
        ans+=t/5;
        t/=5;
    }
    int cnt2=ans,cnt5=ans,ans1=1;
    for(int i=1;i<=n;i++) //求阶乘 
	{
        int t=i;
        while(cnt2&&t%2==0)t>>=1,cnt2--; // 减少因子 2 的个数 
        while(cnt5&&t%5==0)t/=5,cnt5--; // 减少因子 5 的个数 
        ans1=ans1*t%base; //结果取模 
    }
    cout<<setw(k)<<setfill('0')<<ans1<<' ';
    cout<<ans<<endl;
    return 0;
}

末尾 10 的个数代表了因子 2 和 5 的个数,所以在求阶乘时提前除去因子 2 和 5 就可以简化取模时的运算

7-8 三足鼎立 (25分)

在这里插入图片描述

//先看最下面的题解

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;

int a[maxn];
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //加快 cin 与 cout的速度 
    int n,s;
    cin>>n>>s; //n ,相当于已知 A 
    for(int i=1;i<=n;i++)cin>>a[i];
    sort(a+1,a+1+n);
    ll ans=0;
    for(ll i=1;i<=n;i++) //穷举 B 
	{ //寻找 C,从 a+i+1 开始搜索可以避免 B 与 C 重复
        ll q=lower_bound(a+1+i,a+1+n,s+a[i])-(a+1); //不满足 A+B>C 的最小下标 
        ll p=upper_bound(a+1+i,a+1+n,abs(s-a[i]))-(a+1); //满足 B-A<C 与 A-B<C 的最大下标
        ans+=q-p; //中间就是满足条件的 C,加起来即可 
    }
    cout<<ans<<endl;
    return 0;
}

思路:ABC三个国家,已知 A,穷举 B,寻找 C
寻找的条件:满足 A+B>CB-A<CA-B<C

关于 lower_bound/upper_bound

lower_bound( begin,end,num)查找第一个大于或等于 num 的数字,找到返回该数字的地址,不存在则返回 end
upper_bound( begin,end,num)查找第一个大于 num 的数字,找到返回该数字的地址,不存在则返回 end

猜你喜欢

转载自blog.csdn.net/CourserLi/article/details/106256824
520
PTA