河南省多校连萌(四)

来源:互联网 发布:mac brew install m4 编辑:程序博客网 时间:2024/04/29 08:22

https://acm.zzuli.edu.cn/zzuliacm/contest.php?cid=1242

A
居然卡了map

#include<stdio.h>#include<math.h>#include<string.h>#include<vector>#include<queue>#include<map>#include<algorithm>using namespace std;const int INF  = 0x3f3f3f3f;const int MAXN = (int)5e5 + 5;int arr[MAXN];int main(){    int n;    while(scanf("%d", &n) != EOF) {    int cnt = 1;    for(int i = 0; i < n; ++i) {        scanf("%d", arr + i);    }    sort(arr, arr + n);    for(int i = 1; i < n; ++i) {        if(arr[i] == arr[i - 1]) continue;        ++cnt;    }    puts(cnt > n - cnt ? "Yes" : "No");    }    return 0;}

B
是个很有意思的题
最初的想法是反正是要去掉路径中最大的边,那么直接维护路径中最大边权,直接优先减去最大边权的路径距离跑Dijkstra
后来发现是不正确的,比如你从节点1出发到节点n去,现在在节点i,我们维护了路径 1 -> i 的最大边权,而有可能出现需要剪掉的最大边权在 i -> n 的路径中
所以1 和 n 为起点跑两遍最短路,在跑第二遍最短路的时候维护一下答案即可

#include<stdio.h>#include<string.h>#include<queue>#include<vector>#include<algorithm>using namespace std;const int INF = 0x3f3f3f3f;const int MAXS = 60 * 1024 * 1024;char buf[MAXS], *ch;void read(int &x) {    while(*ch <= 32) ++ch;    for(x = 0; *ch >= '0'; ++ch) x = x * 10 + *ch - '0';}const int MAXN = (int)1e3 + 5;struct edge{int to, cost, nxt;} E[MAXN * MAXN]; int lnk[MAXN], sz;void add(int x, int y, int c) {    E[sz] = {y, c, lnk[x]};    lnk[x] = sz++;}int d[MAXN], dd[MAXN], MA[MAXN], n, m;struct node{int v, val, ma;};bool operator < (const node &x, const node &y) {    return x.val > y.val;}void slove() {    memset(d, 0x3f, sizeof(d));    memset(MA, 0, sizeof(MA));    d[1] = 0;    priority_queue<node> que;    que.push({1, 0, 0});    while(!que.empty()) {        node e = que.top(); que.pop();        if(d[e.v] < e.val) continue;        MA[e.v] = e.ma;        for(int i = lnk[e.v]; i; i = E[i].nxt) {            int dis = d[e.v] + E[i].cost + e.ma - max(e.ma, E[i].cost);            if(dis < d[E[i].to]) {                d[E[i].to] = dis;                que.push({E[i].to, dis, max(e.ma, E[i].cost)});            }        }    }    int ans = INF;    memset(dd, 0x3f, sizeof(dd));    dd[n] = 0;    que.push({n, 0, 0});    while(!que.empty()) {        node e = que.top(); que.pop();        if(dd[e.v] < e.val) continue;        ans = min(ans, e.val + e.ma + d[e.v]);        ans = min(ans, e.val + MA[e.v] + d[e.v]);        for(int i = lnk[e.v]; i; i = E[i].nxt) {            int dis = dd[e.v] + E[i].cost + e.ma - max(e.ma, E[i].cost);            if(dis < dd[E[i].to]) {                dd[E[i].to] = dis;                que.push({E[i].to, dis, max(e.ma, E[i].cost)});            }        }    }    if(ans == INF) puts("Impossible");    else printf("%d\n", ans);}int main(){    fread(buf, MAXS, 1, stdin);    ch = buf;    int T;    read(T);    while(T--) {        sz = 1;        memset(lnk, 0, sizeof(lnk));        read(n);        read(m);        for(int i = 0; i < m; ++i) {            int x, y, c;            read(x);            read(y);            read(c);            add(x, y, c);            add(y, x, c);        }    slove();    }    return 0;}

C

#include<stdio.h>#include<math.h>#include<string.h>#include<vector>#include<queue>#include<map>#include<algorithm>using namespace std;const int INF  = 0x3f3f3f3f;const int MAXN = (int)1e3 + 5;int arr[MAXN];int main(){    int T;    scanf("%d", &T);    while(T--) {    int n, m ;    scanf("%d%d", &n, &m);    for(int i = 1; i <= n; ++i) {        scanf("%d", arr + i);    }    arr[++n] = 101;    int ans = 0;    for(int i = 0; i <= n; ++i) {        int low = arr[i];        int top = i + m + 1 <= n ? arr[i + m + 1] - 1 : 100;        ans = max(ans, top - low);    }     printf("%d\n", ans);    }    return 0;}

D

#include<stdio.h>#include<math.h>#include<string.h>#include<vector>#include<queue>#include<map>#include<algorithm>using namespace std;const int INF  = 0x3f3f3f3f;const int MAXN = (int)1e3 + 5;int main(){    int n;    while(scanf("%d", &n) != EOF) {        int cnt2 = 0, cnt4 = 0, cnt0 = 0;        for(int i = 0; i < n; ++i) {            int x;            scanf("%d", &x);            if(x % 4 == 0) ++cnt4;            else if(x % 2 == 0) ++cnt2;            else ++cnt0;        }        puts(cnt4 >= cnt0 || (cnt2 == 0 && cnt4 + 1 >= cnt0) ? "Pass" : "Not Pass");    }    return 0;}

E
这就是高中的等比数列求和,只是是在模意义下的,会模逆元就能AC了

#include<stdio.h>#include<math.h>#include<string.h>#include<vector>#include<queue>#include<map>#include<algorithm>using namespace std;const int INF  = 0x3f3f3f3f;const int MAXN = (int)1e3 + 5;const int MOD = (int)1e9 + 7;int modpow(int a, int n) {    int res = 1;    while(n) {    if(n&1) res = 1LL * res * a % MOD;        a = 1LL * a * a % MOD;        n >>= 1;    }    return res;}int main(){    int k, n, t = 0;    while(scanf("%d%d", &k, &n) != EOF) {        if(k == 1) {            printf("Case %d: %d\n", ++t, n + 1);            continue;        }        int ans = 1LL * (modpow(k, n + 1) - 1) % MOD * modpow(k - 1, MOD - 2) % MOD;        printf("Case %d: %d\n", ++t, ans);    }    return 0;}

F
n! 因子2 的个数

#include<stdio.h>#include<math.h>#include<string.h>#include<vector>#include<queue>#include<map>#include<algorithm>using namespace std;const int INF  = 0x3f3f3f3f;const int MAXN = (int)1e3 + 5;int main(){    int T;    scanf("%d", &T);    while(T--) {        int n;        scanf("%d", &n);        int ans = 0, t = 1;        while(n) {            n /= 2;            ans += n;        }        printf("%d\n", ans);    }    return 0;}

H
一个很重要的条件就是两个子序列长度为 n/2,可以利用这个条件加一个很强的剪枝,也就是说每个数值都要利用,那么用 vis[] 记录是否用过,第一个序列的下一个元素是之后没有用过的的第一个,然后再枚举第二个序列的下一个元素。

#pragma GCC optimize ("O2")#include<stdio.h>#include<string.h>int n, arr[50], vis[50], flag;void dfs(int p1, int p2, int cnt) {    if(flag || cnt == n) {        flag = 1;        return ;    }    int i = p1, j = p2;    for(; i <= n; ++i) if(!vis[i]) break;    if(i == n + 1) return ;    vis[i] = 1;    for(; j <= n; ++j) if(!vis[j] && arr[i] == arr[j]) {        vis[j] = 1;        dfs(i + 1, j + 1, cnt + 2);        vis[j] = 0;    }    vis[i] = 0;}int main(){    int T;    while(scanf("%d", &T) !=EOF  && T) {        while(T--) {            memset(vis, 0, sizeof(vis));            flag = 0;            scanf("%d", &n);            for(int i = 1; i <= n; ++i) {                scanf("%d", arr + i);            }            dfs(1, 1, 0);            printf(flag ? "竟然还有这种操作\n" : "没有这种操作\n");        }    }    return 0;}

I
二元函数 f(x,y)=ax+by(x,yZ) 的值域为 {kgcd(a,b)|kZ}
ax+by 要组成任何数,那么 gcd(a,b)1

下面是官方题解了:
每个都可以到达k的倍数,则
k*x-(2*n-2)*y=C (1<=C<=2*n-2)
必须有解,既gcd(k,2*n-2)==1

#include<stdio.h>int gcd(int a, int b) {    return b ? gcd(b, a % b) : a;}int main(){    int n, k;    while(scanf("%d%d", &n, &k) != EOF)        puts(gcd(2 * n - 2, k) != 1 ? "Yes" : "No");    return 0;}

后面的题会了再补上

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩不爱学英语怎么办 孩子抵触学英语怎么办 初三了英语不好怎么办 孩子入园焦虑怎么办 家长总是说孩子怎么办 幼师打了小朋友怎么办 幼儿园老师欺负孩子怎么办 被老师冷落怎么办豆瓣 不满老师对孩子怎么办 老师总找茬孩子 怎么办 老师总针对孩子怎么办 老师看你不舒服怎么办 高中孩子不爱学习怎么办 孩子太倔不听话怎么办 老师老说孩子怎么办 孩子13不懂礼貌怎么办 老师不重视你 怎么办 我娃好动不听话怎么办 初三娃不听话该怎么办 小孩爱动不听话怎么办 宝宝吃饭讨神怎么办 孩子速度太慢怎么办 一年级做作业慢怎么办 小学三年级数学差怎么办 拼音基础太差怎么办 小孩学拼音差怎么办? 孩子字词基础差怎么办 孩子的语文不好怎么办 数学一直学不好怎么办 小孩数学成绩差怎么办 理科生语文不好怎么办 小学阅读题不好怎么办 如果孩子考不好怎么办 6岁不认识数字怎么办 数学一点都不会怎么办 初一数学太差怎么办 三年级孩子数学差怎么办 三年级孩子数学很差怎么办 初中学习不好高中怎么办 四年级孩子数学不好怎么办 孩子学习不开窍怎么办