2022 nc多校#1

nc多校#1

G Lexicographical Maximum

题意:输出1~n中最大字典序数字

思路:签到题,很容易得出最大字典序的符号是9, 然后最大限度的填9,与n的字典序比较,若n较大输出n否则输出999…99

#include<iostream>
#include<string>

using namespace std;

int main(){
	string n;
	cin >> n;
	string res;
	for (int i = 0; i < n.size()-1; i++) res += '9';
	if (res > n) cout << res;
	else cout << n;
	return 0;
}

A Villages: Landlines

题意:数轴上有一个发电站,n-1个建筑,给定他们的坐标和每一个连接电塔的范围,发电站和建筑都可以无线连接给定r范围内的电塔,电塔数量不限,但是电塔之间相连必须通过电线相接,要使所有的建筑和发电站形成一个连通图,求最短线路。

思路:说到形成连通图,第一想法是并查集什么的,但是每一个建筑及其所能连接到的最远电塔形成一个区间,只要最后所有的区间之间没有空隙即可,一道区间合并问题。

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;
#define PII pair<int, int>
#define lc first
#define rc second
typedef long long LL;

const int N = 2e5+10, inf = 0x3f3f3f3f;

int n, x[N], r[N];
PII a[N];

int main(){
	cin >> n;
	for (int i = 0; i < n; i++){
		cin >> x[i] >> r[i];
		a[i] = {x[i]-r[i], x[i]+r[i]};
	}
	sort(a, a+n);
	vector<PII> sec;
	
	int start = -inf, end = -inf; 
	for(int i = 0; i < n; i++){
		if (start == -inf) start = a[i].lc, end = a[i].rc;
		else{
			if (end < a[i].lc){
				sec.push_back({start, end});
				start = a[i].lc, end = a[i].rc;
			}
			else end = max(end, a[i].rc);
		}
	}
	if (start != -inf) sec.push_back({start, end});
	LL res = 0;
	for (int i = 1; i < sec.size(); i++){
		res += sec[i].lc-sec[i-1].rc;
	}
	cout << res;
	return 0;
}

D Mocha and Railgun

题意:给定一个圆和严格位于圆内的一点 P,Mocha 会从点 P 向任意角度发射一个长度为 2d 的电磁炮,电磁炮底边的中点为点 P 且两端位于圆内,询问单次发射能摧毁的最大圆弧长

思路:无论当前的电磁炮旋转角度如何,我们可以固定电磁炮的方向,将点 Q绕原点旋转,从而使得电磁炮方向竖直向上(即 y 轴正方向)。那么我们可以将题目转化成为电磁炮的方向总是竖直向上的,点 Q 绕原点旋转一周的过程中可以摧毁的最长墙壁长度。并且题目保证了 base segment 总是位于圆内部的,那么我们设点 Q 到原点距离是 dis,点 Q 绕原点旋转一周就可以转化成点 Q 在以 (dis, 0) 和 (dis,0) 为端点的线段上移动

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int n;
int main() {
    int t;
	cin >> t;
    while (t--) {
        double r, x, y, d;
		cin >> r >> x >> y >> d;
        double l =sqrt(x*x+y*y);
        double la = l + d, lb = l - d;
        double a = acos(la / r), b = acos(lb / r);
        double ans = a - b;
        ans *= r;
        printf("%.8lf\n", ans);
    }
    return 0;
}

   

I Chiitoitsu

题意:初始手牌有 13 张麻将牌(一共有(9*3+7) *4)张),相同牌至多出现 2 张,每轮可以从牌堆摸牌,若达成七对子则自摸胡牌

,若不然则选择手牌中某张牌并丢弃之,给定初始手牌,求最优策略下达成七对子的期望轮数

思路:由于初始手牌中每种牌最多两张,因此最优策略是,若摸到的牌能凑成,对子则丢弃单牌,否则丢弃摸到的牌。

考虑 DP 求期望,令 f(s,r) 表示当前手牌中有 s 张单牌且牌堆中剩余 r 张牌时达成七对子的期望轮数,则有: f ( s , r ) = 1 + r − 3 r f ( 1 , r − 1 ) ( s = 1 ) f(s,r) = 1+\frac{r-3}{r}f(1,r-1)(s=1) f(s,r)=1+rr3f(1,r1)(s=1) , f ( s , r ) = 1 + 3 s r f ( s − 2 , r − 1 ) + r − 3 s r f ( s , r − 1 ) ( s > 1 ) f(s,r) = 1+\frac{3s}{r}f(s-2,r-1)+\frac{r-3s}{r}f(s,r-1)(s>1) f(s,r)=1+r3sf(s2,r1)+rr3sf(s,r1)(s>1)

对于给定的初始手牌,设其单牌数量为 s 0 s_0 s0, f ( s 0 , 136 − 13 ) f(s_0, 136-13) f(s0,13613) 即为答案。

#include <bits/stdc++.h>

#define int long long

using namespace std;
const int mod = 1e9 + 7;
int dp[10][200];

int pow(int x,int k) {
    int a = x;
    int res = 1;
    while (k) {
        if (k & 1) {
            res = res * a % mod;
        }
        a = a * a % mod;
        k >>= 1;
    }
    return res;
}

int inv(int x) {
    return pow(x, mod - 2) % mod;
}

signed main() {
    int lst = 34 * 4 - 13;
    for (int i = 0; i <= lst; i++) {
        dp[7][lst] = 0;
    }
    for (int i = 6; i >= 0; i--) {
        int flag = 13 - i * 2;
        for (int j = 1; j <= lst; j++) {
            if(j<flag * 3) {
                continue;
            }
            int p1 = flag * 3 * inv(j) % mod;
            int p2 = (j - flag * 3) * inv(j) % mod;
            dp[i][j] = 1 + p1 * dp[i + 1][j - 1] % mod + p2 * dp[i][j - 1] % mod;
            dp[i][j] %= mod;
        }
    }
    int t;
    cin >> t;
	int k = 1;
    while (t--) {
        string s;
        cin >> s;
        map<string, int> mp;
        int cnt[3];
        cnt[1] = cnt[2] = 0;
        for (int i = 0; i < 26; i += 2) {
            string temp;
            temp += s[i];
            temp += s[i + 1];
            mp[temp]++;
            cnt[mp[temp]]++;
            cnt[mp[temp] - 1]--;
        }
        cout << "Case #" << k << ": ";
        cout << dp[cnt[2]][lst] << "\n";
		k++;
    }
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值