Problem 1 无聊的gcd(gcd.c/cpp/pas)
话说出题人不会被查水表吧。
简单的问题描述:从N个正整数里面取出K个数的最大公因数最大是多少。(请将答案乘上k之后输出哦,谢谢合作。)
输入格式
第一行两个正整数N,K。
第二行n个正整数
输出格式
输出一个正整数表示最大的最大公因数。
样例输入
3 1
1 2 3
样例输出
3
数据说明
对于30%的数据,保证k≤n≤20。
对于50%的数据,保证输入中所有数小于5000。
对于100%的数据,保证输入中所有数小于500000,k≤n。
0表示不取 1表示取
用i的二进制表示状态 比如i=10101表示取1,3,5 i=00110表示取3,4
如果1有k个
那么i代表的状态选了k个数
for一遍把i表示的状态取了的数的gcd取出来
#include <cstdio> #include<iostream> using namespace std; const int Maxn = 40; int a[Maxn],n,k,ans=0; int gcd(int a,int b) { return b ? gcd(b,a%b) : a; } int max(int a,int b) { return a < b ? b : a ; } int main() { scanf("%d%d",&n,&k); for(int i=0;i<n;++i)scanf("%d",&a[i]);//读入 for(int i=1;i<(1<<n);++i) { int tmp = 0; for(int j=0;j<n;++j) { if(i&(1<<j)) ++tmp; //tmp表示选了几个数 } // printf("i = %d : tmp = %d ",i,tmp); if(tmp==k)//如果选了k个 { tmp=-1; for(int j=0;j<n;++j) { if(i&(1<<j)) { if(tmp==-1) tmp=a[j]; else tmp=gcd(a[j],tmp); } } ans = max(ans,tmp); // printf("ans : %d ",ans); } } printf("%d",ans*k); puts(""); return 0; }
如果i&(1<<j) == 1的话那么i的第j位就是1
因为1<<j是...001000...的形式存在,所以和 i 与起来,要是 i 这一位是 1 , 就是1,i 这一位是0,就是0
所以 i&(1<<j) 表示 i 在二进制下的第 j 位
因为1<<0 = 1 这时候j=0 如果从1存的话就变成1<<1 = 2 那就时间复杂度*2 所以从0开始读
首先所有输入数字不大于50W,那么我们开一个50W的数组,记下每个数字出现多少次
然后就有一些有意思的事情发生了
我们从小到大枚举答案 每个答案x,判定可行的方法就是遍历每一个x的倍数
那么只要把所有x的倍数统计一下有多少看看是不是大于等于k就好了
如果我选的是这k个x的倍数,那么我们不就知道答案至少是x了
Problem 2 虫洞(wormhole.cpp/c/pas)
【题目描述】
John在他的农场中闲逛时发现了许多虫洞。虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前)。John的每个农场有M条小路(无向边)连接着N (从1..N标号)块地,并有W个虫洞(有向边)。其中1<=N<=500,1<=M<=2500,1<=W<=200。 现在John想借助这些虫洞来回到过去(出发时刻之前),请你告诉他能办到吗。 John将向你提供F(1<=F<=5)个农场的地图。没有小路会耗费你超过10000秒的时间,当然也没有虫洞回帮你回到超过10000秒以前。
【输入格式】
* Line 1: 一个整数 F, 表示农场个数。
* Line 1 of each farm: 三个整数 N, M, W。
* Lines 2..M+1 of each farm: 三个数(S, E, T)。表示在标号为S的地与标号为E的地中间有一条用时T秒的小路。
* Lines M+2..M+W+1 of each farm: 三个数(S, E, T)。表示在标号为S的地与标号为E的地中间有一条可以使John到达T秒前的虫洞。
【输出格式】
* Lines 1..F: 如果John能在这个农场实现他的目标,输出"YES",否则输出"NO"。
【样例输入】
2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8
【样例输出】
NO
YES
1.一个点如果经过一个环以后dis一直在变小,那么显然这个环是负环
2.如果没有负环一个点最多进队n次(每条只想j的边都维护一遍dis)
所以vis记成int,int vis[Maxn];
Problem 3 机器人(robot.cpp/c/pas)
【题目描述】
早苗入手了最新的Gundam模型。最新款自然有着与以往不同的功能,那就是它能够自动行走,厉害吧。
早苗的新模型可以按照输入的命令进行移动,命令包括‘E’、‘S’、‘W’、‘N’四种,分别对应东南西北。执行某个命令时,它会向对应方向移动一个单位。作为新型机器人,它可以执行命令串。对于输入的命令串,每一秒它会按命令行动一次。执行完命令串的最后一个命令后,会自动从头开始循环。在0时刻时机器人位于(0,0)。求T秒后机器人所在位置坐标。
【输入格式】
第1行:一个字符串,表示早苗输入的命令串,保证至少有1个命令
第2行:一个正整数T
【输出格式】
2个整数,表示T秒时,机器人的坐标。
【样例输入】
NSWWNSNEEWN
12
【样例输出】
-1 3
【数据范围】
对于60%的数据 T<=500,000 且命令串长度<=5,000
对于100%的数据 T<=2,000,000,000 且命令串长度<=5,000
【注意】
向东移动,坐标改变改变为(X+1,Y);
向南移动,坐标改变改变为(X,Y-1);
向西移动,坐标改变改变为(X-1,Y);
向北移动,坐标改变改变为(X,Y+1);
由于t特别大然后操作序列最长只有5000
就先做一遍操作序列,看看做完一整个序列之后,x和y是变化量是多少,并记录这个变化量
用t除以长度,剩下的就是取模了就是t%长度 就知道要做到哪里了
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; char ch[5005]; int t,nn=0; int xx=0,yy=0; int x=0,y=0; int main() { scanf("%s%d",ch+1,&t); int n=strlen(ch+1); for(int i=1;i<=n;++i) { if(ch[i]=='N')yy++; if(ch[i]=='S')yy--; if(ch[i]=='W')xx--; if(ch[i]=='E')xx++; } nn=t/n; t%=n; for(int i=1;i<=t;++i) { if(ch[i]=='N')y++; if(ch[i]=='S')y--; if(ch[i]=='W')x--; if(ch[i]=='E')x++; } cout<<x+xx*nn<<" "<<y+yy*nn; puts(""); return 0; }