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+rr−3f(1,r−1)(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(s−2,r−1)+rr−3sf(s,r−1)(s>1)
对于给定的初始手牌,设其单牌数量为 s 0 s_0 s0, f ( s 0 , 136 − 13 ) f(s_0, 136-13) f(s0,136−13) 即为答案。
#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;
}