蓝桥杯 历届试题 约数倍数选卡片 (经典数论+DFS)
闲暇时,福尔摩斯和华生玩一个游戏:
在N张卡片上写有N个整数。两人轮流拿走一张卡片。要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数。例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可以拿的数字包括:
1,2,3, 6,12,18,24 ....
当轮到某一方拿卡片时,没有满足要求的卡片可选,则该方为输方。
请你利用计算机的优势计算一下,在已知所有卡片上的数字和可选哪些数字的条件下,怎样选择才能保证必胜!
当选多个数字都可以必胜时,输出其中最小的数字。如果无论如何都会输,则输出-1。
Input
输入数据为2行。第一行是若干空格分开的整数(每个整数介于1~100间),表示当前剩余的所有卡片。
第二行也是若干空格分开的整数,表示可以选的数字。当然,第二行的数字必须完全包含在第一行的数字中。
第二行也是若干空格分开的整数,表示可以选的数字。当然,第二行的数字必须完全包含在第一行的数字中。
Output
程序则输出必胜的招法!!
Sample Input
样例输入1 2 3 6 3 6 样例输入2 1 2 2 3 3 4 5 3 4 5
Sample Output
样例输出1 3 样例输出2 4
Source
蓝桥杯
code:
#include<bits/stdc++.h> using namespace std; typedef long long LL; #define INF 99999999 #define me(a,x) memset(a,x,sizeof(a)) int mon1[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int mon2[13]= {0,31,29,31,30,31,30,31,31,30,31,30,31}; int dir[4][2]= {{0,1},{0,-1},{1,0},{-1,0}}; int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};//i的阶乘 LL getval() { LL ret(0); char c; while((c=getchar())==' '||c=='\n'||c=='\r'); ret=c-'0'; while((c=getchar())!=' '&&c!='\n'&&c!='\r') ret=ret*10+c-'0'; return ret; } void out(int a) { if(a>9) out(a/10); putchar(a%10+'0'); } int kt(int a[],int n)//康托展开 { int ans=0; for(int i=1; i<=n; i++) //下标从1开始 { int c=0; for(int j=i+1; j<=n; j++) { if(a[j]<a[i]) c++; } ans+=(c*fac[n-i]); } return ans+1; } #define max_v 105 int a[max_v]; vector<int> b; vector<int> vv[max_v]; int dfs(int x) { for(int i=vv[x].size()-1; i>=0; i--)//从大的数开始选,因为大的数约数和倍数少 { int y=vv[x][i]; if(a[y])//对手选择的数字存在 { a[y]--; int flag=dfs(y);//判断对手是否为必胜态 a[y]++; if(flag)//对手为必胜态,则我为必败态 return 0; } } return 1;//对手没有必胜态,则我是必胜态 } int main() { int x; me(a,0); string str; getline(cin,str); stringstream ss(str); while(ss>>x) a[x]++; getline(cin,str); stringstream st(str); while(st>>x) b.push_back(x); sort(b.begin(),b.end()); for(int i=1; i<=100; i++) { if(a[i]!=0) { for(int j=1; j<=100; j++)//得到每个i的倍数或者约数 { if((i%j==0||j%i==0)&&a[j]!=0) vv[i].push_back(j); } } } int flag=0; for(int i=0; i<b.size(); i++) { int x=b[i];//我先手选 if(a[x])//选的数字存在 { a[x]--;//选了一个 if(dfs(x))//搜索判断我选择该数字是否为必胜态 { printf("%d\n",x); flag=1; break; } a[x]++;//回退 } } if(flag==0) printf("-1\n"); return 0; }
心之所向,素履以往
分类:
ACM
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南