ACDream - k-GCD

先上题目:

B - k-GCD

Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)

SubmitStatus

Problem Description

给出n个数a[1], a[2]...... a[n]和一个正整数k, 让你在这n个数中任取k个数并求它们的GCD, 问最大的GCD是多少。
   PS: k = 1时, GCD等于所选数本身。

Input

第一行一个整数T代表测试数据的组数。
每组测试数据有两行。
第一行有两个整数n, k;
第二行有n个整数a[1], a[2]...... a[n]:

1 <= T <= 100;
2 <= k <= n <= 10000;
1 <= a[i] <= 10000;

Output

每组数据输出一行,一个整数代表最大的GCD。

Sample Input

2
5 3
12 36 20 15 9
5 4
12 36 20 15 9

Sample Output

4
3

  其实这一题原本不算难,但是为什么一开始会想不到?大概是脑子习惯地去想可能需要的时间复杂度要在O(n)~O(n^2),然后就会很容易想到底是O(n)还是O(nlogn)还是O(n^2),换而言之,我们很容易不去算时间复杂度而是下意识想题目的样子大概是什么时间复杂度,往往会忘了时间复杂度的提示就在题目里面,根本不用乱猜。  这一题的做法是把每一个数的每一个因子都求出来然后判断所有因子中,哪一种是大于等于k的,选最大的那个因子。时间复杂度只有O(n^(3/2))。

上代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 #define MAX 10002
 6 using namespace std;
 7
 8 int a[MAX];
 9 int s[MAX];
10 int maxn,mm,n,k;
11
12 int main()
13 {
14     int t,sq,e;
15     //freopen("data.txt","r",stdin);
16     scanf("%d",&t);
17     while(t--){
18         memset(s,0,sizeof(s));
19         scanf("%d %d",&n,&k);
20         for(int i=0;i<n;i++) scanf("%d",&a[i]);
21         mm=0;
22         for(int i=0;i<n;i++){
23             mm = max(a[i],mm);
24             sq = (int)sqrt(a[i]*1.0);
25             for(int j=1;j<=sq;j++){
26                 if(a[i]%j==0){
27                     s[j]++;
28                     e = a[i]/j;
29                     if(e != j)s[a[i]/j]++;
30                 }
31             }
32         }
33         maxn=0;
34         for(int i=1;i<=mm;i++){
35             if(s[i]>=k) maxn = i;
36         }
37         printf("%d\n",maxn);
38     }
39     return 0;
40 }

k-GCD

ACDream - k-GCD

时间: 2024-10-15 15:20:24

ACDream - k-GCD的相关文章

ACdream 1148 GCD SUM (久违的莫比乌斯)

题目链接 题意:给出N,M 执行如下程序: long long  ans = 0,ansx = 0,ansy = 0; for(int i = 1; i <= N; i ++) for(int j = 1; j <= M; j ++) if(gcd(i,j) == 1) ans ++,ansx += i,ansy += j; cout << ans << " " << ansx << " " <<

acdream 1148 GCD SUM 莫比乌斯反演 ansx,ansy

GCD SUM Time Limit: 8000/4000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description 给出N,M执行如下程序:long long  ans = 0,ansx = 0,ansy = 0;for(int i = 1; i <= N; i ++)   for(int j = 1; j <= M; j ++)     

hdu1695 GCD2 容斥原理 求x属于[1,b]与y属于[1,d],gcd(x,y)=k的对数。(5,7)与(7,5)看作同一对。

GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 10992 Accepted Submission(s): 4157 Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k

dutacm.club 1094: 等差区间(RMQ区间最大、最小值,区间GCD)

1094: 等差区间 Time Limit:5000/3000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)Total Submissions:655   Accepted:54 [Submit][Status][Discuss] Description 已知一个长度为 n 的数组 a[1],a[2],-,a[n],我们进行 q 次询问,每次询问区间 a[l],a[l+1],-,a[r?1],a[r] ,数字从小到大

POJ 2429 GCD &amp; LCM Inverse

设答案为ans1,ans2 ans1=a1*gcd,ans2=a2*gcd,a1,a2互质 gcd*a1*b1=lcm,gcd*a2*b2=lcm a1*b1=lcm=(ans1*ans2)/gcd=a1*a2 综上所诉,a1=b2,a2=b1. 也就是说,ans1=gcd*k1,ans2=gcd*k2 要求k1,k2尽量接近,并且k1,k2互质,并且,k2*k2=lcm/gcd 需要用到Pollard_rho分解质因数,然后暴力搜索寻找k1,k2.用了kuangbin大神的Pollard_rh

求最大公约数(GCD)的两种算法

之前一直只知道欧几里得辗转相除法,今天学习了一下另外一种.在处理大数时更优秀的算法--Stein 特此记载 1.欧几里得(Euclid)算法 又称辗转相除法,依据定理gcd(a,b)=gcd(b,a%b) 实现过程演示: sample:gcd(15,10)=gcd(10,5)=gcd(5,0)=5 C语言实现: 1 int Euclid_GCD(int a, int b) 2 { 3 return b?Euclid_GCD(b, a%b):a; 4 } 2.Stein 算法 一般实际应用中的整数

ACM数论之旅3---最大公约数gcd和最小公倍数lcm(苦海无边,回头是岸( ̄? ̄))

gcd(a, b),就是求a和b的最大公约数 lcm(a, b),就是求a和b的最小公倍数 然后有个公式 a*b = gcd * lcm     ( gcd就是gcd(a, b), ( •?∀•? ) 简写你懂吗) 解释(不想看就跳过){ 首先,求一个gcd,然后... a / gcd 和 b / gcd 这两个数互质了,也就是 gcd(   a / gcd ,b / gcd  )  =  1,然后... lcm = gcd *  (a / gcd) * (b / gcd) lcm = (a *

hdu 4983 Goffi and GCD(数论)

题目链接:hdu 4983 Goffi and GCD 题目大意:求有多少对元组满足题目中的公式. 解题思路: n = 1或者k=2时:答案为1 k > 2时:答案为0(n≠1) k = 1时:需要计算,枚举n的因子,令因子k=gcd(n?a,n, 那么另一边的gcd(n?b,n)=nk才能满足相乘等n,满足k=gcd(n?a,n)的a的个数即为?(n/s),欧拉有o(n ̄ ̄√的算法 #include <cstdio> #include <cstring> #include

poj2115--C Looooops(扩展gcd)

C Looooops Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17740   Accepted: 4600 Description A Compiler Mystery: We are given a C-language style for loop of type for (variable = A; variable != B; variable += C) statement; I.e., a loop w

HTPJ 1268 GCD

链接: http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1268 题意: 给出n,m,定义f(t)=min |i/n−j/m+t| (i,j∈Z) .求f(t)的最大值 题解: i/n-j/m = (i*m - j*n) / (n*m),分子 = k*gcd(n,m).令d = gcd(n,m), 所以就是求 min |k*d / (n*m) +t| 的最大值,所以相邻两个结果之间的距离为d / (n*m), 要想让值最大