【模拟赛】飞旭杯-迎接NOIP2018

版权声明:Fashion Education https://blog.csdn.net/ModestCoder_/article/details/83756567


@飞旭杯-迎接NOIP2018

刷一场普及难度的比赛心情好~~
我是不会告诉你这场比赛是我同学出的


T1:帅哥(Handsome)

签到题,
样例可自行画图理解。
发现:
1、瑶瑶首先要走到帅哥行走的那条直线上
2、向前走一步,再向后走一步等于没走
这样题目就变得很水了

Code:

//对于每个帅哥,先让瑶瑶走到帅哥行走的那条线上,算出之后两人的距离,
//这个距离必须为正偶数
var
    i, n, x, y, x1, y1, ans, s : longint;
    d, kongge : char;

begin
    readln(n, x, y);
    for i := 1 to n do
    begin
        readln(x1, y1, kongge, d);
        if d = 'U' then
        begin
            s := (x1 - x) - abs(y1 - y);
            if (s >= 0) and (s and 1 = 0) then inc(ans);
        end else
        if d = 'L' then
        begin
            s := (y1 - y) - abs(x1 - x);
            if (s >= 0) and (s and 1 = 0) then inc(ans);
        end else
        if d = 'R' then
        begin
            s := (y - y1) - abs(x - x1);
            if (s >= 0) and (s and 1 = 0) then inc(ans);
        end else
        if d = 'D' then
        begin
            s := (x - x1) - abs(y - y1);
            if (s >= 0) and (s and 1 = 0) then inc(ans);
        end;
    end;
    writeln(ans);
end.


T2:旭数(Xu)

数据范围很小,1000000内质数很少
筛出1000000内所有质数,
旭数=18 * 质数+36 * 质数,所以只要O(质数个数^2)枚举就行了
最后搞个前缀和
筛法用普通筛都能过,线筛的话更快一点

Code:

const
    maxn = 1000000;
var
    flag, xu : array[0..maxn] of boolean;
    sum, prime : array[0..maxn] of longint;
    n, l, r, i, j, tot : longint;

begin
    for i := 2 to maxn do
    begin
        if not flag[i] then
        begin
            inc(tot);
            prime[tot] := i;
        end;
        for j := 1 to tot do
        begin
            if i * prime[j] > maxn then break;
            flag[i * prime[j]] := true;
            if i mod prime[j] = 0 then break;
        end;
    end;
    for i := 1 to tot do
        for j := 1 to tot do
        begin
            if 18 * prime[i] + 36 * prime[j] > maxn then break;
            xu[18 * prime[i] + 36 * prime[j]] := true;
        end;
    for i := 1 to maxn do sum[i] := sum[i - 1] + ord(xu[i]);
    readln(n);
    for i := 1 to n do
    begin
        readln(l, r);
        writeln(sum[r] - sum[l - 1]);
    end;
end.


T3:得分(Score)

看完题目,马上想到:数据结构?
然后又想到:支持单点修改,查询第k大?
想到了:树状数组!
裸题啊!赤果果的树状数组
不详细介绍了吧,看代码秒懂啊

经主办同学要求,我需要帮他码码T3的c++标程(他不会c++,而且他用的方法是堆),我就在比赛前破例用一次c++(告别pascal还剩6天祭)

Code:

#include <bits/stdc++.h>
#define res register int
#define maxn 3000005
#define inf 2146483647
#define ll long long
using namespace std;
int s[maxn][4], tree[maxn], n, m, a, b, c, k;

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	while (c < '0' || c > '9'){
		if (c == '-') w = -1; c = getchar();
	}
	while (c >= '0' && c <= '9') s = (s << 3) + (s << 1) + (c ^ 48), c = getchar();
	return s * w;
}
inline void add(int x, int y){for (; x <= maxn; x += (x & -x)) tree[x] += y;}
inline int query(int x){int s = 0; for (; x > 0; x -= (x & -x)) s += tree[x]; return s;}
inline int find(int x){
	int s = 0;
	for (int l = 0, r = maxn; l <= r;){
		int mid = (l + r) >> 1;
		if (query(mid) >= x) r = mid - 1, s = mid; else l = mid + 1;
	}
	return s;
}
int main(){
	n = read(), m = read(), a = read(), b = read(), c = read(), k = read();
	for (res i = 1; i <= n; ++ i){
		s[i][1] = read(), s[i][2] = read(), s[i][3] = read();
		add(s[i][1] * a + s[i][2] * b + s[i][3] * c, 1);
	}
	for (res i = 1; i <= m; ++ i){
		int x = read();
		if (x == 0){
			printf("%d\n", find(n + 1 - k));
		} else{
			int x = read(), y = read(), z = read();
			add(s[x][1] * a + s[x][2] * b + s[x][3] * c, -1);
			s[x][y] = z;
			add(s[x][1] * a + s[x][2] * b + s[x][3] * c, 1);
		}
	}
	return 0;
}


T4:校牌(Card)

加强版的小背包问题,我是真的不会啊

本来,是有30分dfs暴搜子任务+30分暴力dp子任务,我就这样拿了60
Code:

uses math;
var
    dp : array[0..32,0..10000000] of longint;
    m, w : array[0..10000] of longint;
    n, k, s, sum, i, j, l, ans : longint;

procedure dfs(t, sum, q, tot : longint);

begin
    if t > n then
    begin
        ans := max(ans, sum); exit;
    end;
    dfs(t + 1, sum, q, tot);
    if (q + m[t] <= s) and (tot < k) then dfs(t + 1, sum + w[t], q + m[t], tot + 1);
end;

procedure do1;

begin
    dfs(1, 0, 0, 0);
    writeln(ans);
    halt;
end;

begin
    readln(n, k, s);
    for i := 1 to n do
    begin
        readln(m[i], w[i]);
        inc(sum, m[i]);
    end;
    if n <= 25 then do1;
    s := min(s, sum);
    for i := 1 to n do
    begin
        for j := k downto 1 do
            for l := s downto m[i] do
                dp[j][l] := max(dp[j][l], dp[j - 1][l - m[i]] + w[i]);
    end;
    writeln(dp[k][s]);
end.

后来,因为有同学用折半搜索水过了@fxkkks,经hsy奆佬要求加强了数据
此题正解:模拟退火(hsy出的题目hsy自己过了),我当然是不会的啦

猜你喜欢

转载自blog.csdn.net/ModestCoder_/article/details/83756567