2022年江西省大学生程序设计竞赛

比赛链接

2022年江西省大学生程序设计竞赛(正式赛)

C.Graphic Game

给一个 2×n 个点,m 条边,没有重边和自环的无向图,每次可以选择两个度数相等的点删除,求删完所有点的方案

解题思路

鸽笼原理

度数的可能取值有 1,,m,而点数 2×n>m 个,即一个无向图最少存在两个点的度数相等,删除两个点后仍然是一个无向图,即该问题一定有解,先存下每个度数对应的节点,考虑从最大的度数开始删除两个数,用 set 维护即可,即现在要证明不存在这样一种情况:删除当前度数为 t 的两个数后,所有度数 x<=t 的节点个数都不超过 1,但是可能存在度数 x>t 的节点个数超过 1,可以发现这样的情况很难构造出来,因为对于一个度数 x>t 的节点来说,说明会有 x 条边由该节点连向其他节点,假设如果其他点的度数都 t,而有 x 个这样的点,说明至少存在两个度数相等的点,假设不成立,故与该节点连的点中至少存在一个点的度数 >t,即我们的那种要证明的不存在的情况说明:度数大的点至少也会跟度数大的点连边,且所有其他度数小的节点都不存在相等度数的节点,这样的情况更加难以构造

  • 时间复杂度:O(nlogn)

代码

// Problem: Graphic Game // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/43898/C // Memory Limit: 524288 MB // Time Limit: 10000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> // #define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=2e6+5,M=1e6+5; int n,m,d[N]; int h[N],e[N],ne[N],idx; set<int>deg[M]; void add(int a,int b) { e[idx]=b,ne[idx]=h[a],h[a]=idx++; } int main() { memset(h,-1,sizeof h); read(n),read(m); for(int i=1;i<=m;i++) { int a,b; read(a),read(b); add(a,b),add(b,a); d[a]++,d[b]++; } for(int i=1;i<=2*n;i++)deg[d[i]].insert(i); int t=m; while(t>=0) { if(deg[t].size()>=2) { int x=*deg[t].begin(); deg[t].erase(deg[t].begin()); int y=*deg[t].begin(); deg[t].erase(deg[t].begin()); printf("%d %d\n",x,y); d[x]=d[y]=0; for(int i=h[x];~i;i=ne[i]) { int j=e[i]; if(d[j]>0) { deg[d[j]].erase(j); d[j]--; deg[d[j]].insert(j); } } for(int i=h[y];~i;i=ne[i]) { int j=e[i]; if(d[j]>0) { deg[d[j]].erase(j); d[j]--; deg[d[j]].insert(j); } } } else t--; } return 0; }

G.A Game of Taking Numbers

对于 n 个数 aiA 先手,A 可以选择任何数,如果 A 选择了 x,则 B 选择的 y 需要满足:|xy|3xy(mod3),最后无法操作者败

解题思路

博弈论

如果 n 为奇数的话 B 必败,否则将所有对 3取模的数分成 3 堆,如果这 3 堆都为偶数的话 A 必败,因为无论 A 从这 3 堆中哪一堆取数,B 都可以从相同堆中取数,最后一定是 A 无法操作,否则剩下    的情况,同理如果两个奇数堆中存在这样的一对数 x,y 使得 |xy|3,则最后 A 选到其中一个数时 B 都可以选择另外一个数,使得 A 面临    的必败态,注意还有一种情况需要考虑,如果   中存在 |xy|3 这样的一对数 x,y,则此时奇偶发生变化,故如果 中至少存在两个不相等的 x,在两个 中都存在 |xy|3 这样的一对数 x,y,则无论 A 选这 4 个数中的任意一个,B 都可以选与此对应的数使得状态仍然是    的情况,但是此时   中还存在这样的一对数使得 A 最后面临    的必败态

  • 时间复杂度:O(n)

代码

// Problem: A Game of Taking Numbers // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/43898/G // Memory Limit: 524288 MB // Time Limit: 4000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } int n,t; int main() { for(scanf("%d",&t);t;t--) { scanf("%d",&n); vector<int> a[3]; for(int i=1;i<=n;i++) { int x; scanf("%d",&x); a[x%3].pb(x); } if(n&1) { puts("His little girlfriend"); continue; } if(a[0].size()%2==0&&a[1].size()%2==0&&a[2].size()%2==0) { puts("rqd"); continue; } bool f=false; for(int i=0;i<2;i++) if(a[i].size()%2==0)swap(a[i],a[2]); unordered_map<int,int> mp[3]; for(int i:a[1])mp[1][i]++; for(int i:a[0]) { mp[0][i]++; for(int j=-3;j<=3;j++) if(mp[1].count(i+j)) { f=true; break; } } bool fl[2]={0}; for(int i=0;i<a[2].size();i++) { bool is[2]={0}; for(int j=-3;j<=3;j++) { if(mp[0].count(a[2][i]+j))is[0]=true; if(mp[1].count(a[2][i]+j))is[1]=true; } if(!is[0]&&!is[1])continue; f|=(is[0]&&fl[1]||is[1]&&fl[0]); if(f)break; if(is[0]&&!is[1])fl[0]=true; else if(is[1]&&!is[0])fl[1]=true; else { bool t=false; for(int k=0;k<a[2].size();k++) { if(k==i)continue; for(int j=-3;j<=3;j++) { if(mp[0].count(a[2][k]+j))t=true; if(mp[1].count(a[2][k]+j))t=true; } } if(t)f=true; break; } } puts(f?"rqd":"His little girlfriend"); } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16819062.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(759)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
历史上的今天:
2021-10-23 组合数
2021-10-23 EOJ Monthly 2021.10
点击右上角即可分享
微信分享提示