XJOI复赛模拟11

A.Trape

背景 :

一个平面上有许多点,LYH需要在这个平面上画一个等腰梯形,LYH希望在这个梯形内的点尽可能得多,LYH让你帮她求梯形内最大点数。(点在梯形边上也算梯形内)

题目描述 :

给出M个点求用一个上底长25,下底长75,高50的等腰梯形最多能框住的点数。

输入格式 :

第一行两个正整数N,M,N表示横坐标在[-N,N],纵坐标在[-N,N]的平面大小, M表示点数。 接下来M行,每行两个整数x,y,为各个点的横纵坐标。

输出格式 :

一行一个正整数为最大点数。

数据范围 :

60% N<=150
80% M<=300
90% M<=3000
100% N<=2500 M<=10000 -N<=x,y<=N

Solution :

题意没写清楚,这个梯形一定是上下底平行于x轴且是正的(上底在上面)。
可以枚举底边左端点所在的纵坐标 \(m\),然后对于每个点\((x[i],y[i])\) 将它们分别对应到 \(y=m\) 上(在 \(x[i]-(y[i] + m)/2\)\(-1\),在 \(x[i]+(y[i]-m)/2-75\)\(+1\) ,表示在该位置有一个点进入或退出梯形),然后求一个最大的前缀和即可

Code :

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define max(x,y) (x>y?x:y)
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
const int N = 10005;
int n, m, x[N], y[N];
pii p[N * 2];
inline bool cmp(pii u, pii v) {
    return u.fi < v.fi || (u.fi == v.fi && u.se > v.se);
}
template<typename T> void read(T &x) {
    bool f = false; x = 0;
    char ch = getchar();
    while (ch<'0' || ch>'9') {if (ch == '-') f = true; ch = getchar();}
    while (ch>='0' && ch<='9') x = x * 10 + ch - '0', ch = getchar();
    if (f) x = -x;
}
int main() {
    read(n), read(m);
    for (int i = 1; i <= m; i++) {
        read(x[i]), read(y[i]);
    }
    int ans = 0;
    for (int i = -n; i <= n; i++) {
        int cnt = 0;
        for (int j = 1; j <= m; j++) {
            if (y[j] < i || y[j] - i > 50) continue;
            //因为坐标差除2可能出现小数所以都*2
            p[++cnt] = mp(2 * x[j] - y[j] + i, -1);
            //-1的位置不需要后移一位,只要排序时让+1在前,那么处理该位置就会先进入在退出
            p[++cnt] = mp(2 * x[j] + y[j] - i -150, 1);
        }
        sort(p + 1, p + 1 + cnt, cmp);
        int now = 0;
        for (int j = 1; j <= cnt; j++) {
            now += p[j].se;
            ans = max(ans, now);
        }
    }
    printf("%d\n", ans);
    return 0;
}

B.Rcomb

题目描述 :

Na老师有\(N\)张卷子排成一列,第i张卷子有其难度\(V_i\),由于X爷的出现,Na老师需要将这些卷子合并为1张。每次Na老师以相等的概率随机选择两张相邻卷子,消耗两张卷子难度和的体力,得到一张难度为两张卷子难度和的卷子,求 Na老师需要消耗的体力期望值。

输入格式 :

第一行:一个整数\(N\)
第二行:\(N\)个整数\(V_1、V_2、...、V_N\)

输出格式 :

只有一行,一个小数ANS(小数点后保留5位)表示Na老师需要消耗的体力期望值。

数据范围 :

30% N<=10
60% N<=100
100% 1<=N<=5000 1<=V_i<=10000

Solution & Code :

#include<bits/stdc++.h>
using namespace std;
const int N = 5005;
int n, a[N];
double dp[2][N];
// dp[i][j] 表示长度为i的序列排在第j位的试卷的期望被计入的次数
// dp[1][1] = 0 长度为 1 没有合并 次数为 0 
template<typename T> void read(T &x) {
    bool f = false; x = 0;
    char ch = getchar();
    while (ch<'0' || ch>'9') {if (ch == '-') f = true; ch = getchar();}
    while (ch>='0' && ch<='9') x = x * 10 + ch - '0', ch = getchar();
    if (f) x = -x;
}
int main() {
    read(n);
    for (int i = 1; i <= n; i++) read(a[i]);
    // dp[0][0] = 0; dp[1][1] = 0;
    for (int i = 2; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            if (j > 1) dp[i&1][j] += dp[(i-1) & 1][j-1] * (j-1) / (i-1) + 1.0 / (i-1);
            //因为每相邻两试卷有相同概率被合并,所以每次合并的期望贡献次数为 1.0/(i-1)
            if (j < i) dp[i&1][j] += dp[(i-1) & 1][j] * (i-j) / (i-1) + 1.0 / (i-1);
        }
        memset(dp[(i-1) & 1], 0, sizeof(dp[(i-1) & 1]));
    }
    double ans = 0;
    for (int i = 1; i <= n; i++) {
        ans += dp[n&1][i] * a[i];
    }
    cout<< fixed << setprecision(5) << ans << endl;
    return 0;
}

C.Game

题目描述 :

给出一个由小写英文字母构成的字符串 S,再取 n 个字符串,它们都是 S 的子串,之后开始游戏,两人轮流操作: 每次选一个串,在其后添加一个英文字母,保证添加后该串仍为 S 的子串。 谁不能操作谁输,或者谁不能操作谁胜。 但是春希看出了胜负已定,于是对实际操作没有兴趣,所以 Pickupwin 只要求他指明先手是否必胜就好。

输入格式 :

第一行一个字符串 S;
第二行一个正整数 n;
接下来 n 行,每行两个正整数 l,r,表示第 i 个字符串由 S 中第 l 个至第 r 个字符一次拼接而成(S 中字符从 1 开始标号)

输出格式 :

输出 n + n行
\(2 * i - 1\) 行输出在仅有前 i 个子串时,谁不能操作谁输,先手是否必胜。
\(2 * i\) 行输出在仅有前 i 个子串时,谁不能操作谁胜,先手是否必胜。
用 Fir 表示先手必胜, Sec 表示后手必胜。

样例 :

输入 :

sroababorz
3 
4 5 
7 8 
1 3

输出 :

Fir 
Sec 
Fir 
Sec 
Sec 
Fir

数据范围 :

50% |S| <= 200,n <= 100
100% |S| <=\(10^6\), n <= \(5*10^5\)

Solution :

(anti-Nim) 占坑待填

猜你喜欢

转载自www.cnblogs.com/bryane/p/11657339.html