k.计软联谊 「游族杯」上海市高校程序设计邀请赛(数论)

时间:2021-05-25 19:21:11

K. 计软联谊

Time limit per test: 7.0 seconds

Memory limit: 512 megabytes

Accept / Submit: 19 / 398

在计算机和软件专业的联谊会上,计算机和软件的同学相间着排成一列。现在要计算相邻两个同学的友谊度。

k.计软联谊 「游族杯」上海市高校程序设计邀请赛(数论)

友谊度  friend(a,b)  是这么计算的:令  a ,  b  两个整数分别是两个同学的属性,两个同学的友谊度取决于  a,b    k  大的公约数。如果不存在,就说明这两个同学之间完全没有友谊,友谊度为  1

Input

第一行是数据组数  T   (1T60)

对于每组数据:
第一行:首先是学生的数量  n   (1n105) ,约定的常数  k   (1k106)
第二行: n  个整数,依次表示这些学生的属性值: m1,m2,,mn   (1mi106)

Output

对于每组数据输出一行,以 Case x: 开头(x 表示数据编号,从 1 开始),后面是  n1  个整数,分别是  friend(m1,m2),friend(m2,m3),,friend(mn1,mn) ,整数和整数之间用空格隔开。

Examples

input
2
3 1
4 6 12
6 2
13 12 12 24 36 30
output
Case 1: 2 6
Case 2: -1 6 6 6 3

Note

请注意输入输出上的优化!

想法:

首先找出1到10^6的因数,最好用<vector>保存

该步骤的代码:

void init()//找每个数的因数
{
    for(int i = 1;i<=L;i++)
    {
        for(int j = i;j<=L;j+=i)
        {
            P[j].push_back(i);
        }
    }
}

再者我们要用欧几里得找出最大公约数

这样我们很容易从<vector>中找出  a,b    k  大的公约数

代码:

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 1e5+10;
const int L = 1e6;
int m[maxn];
vector <int > P[L+1];
int kase = 1;
void init()//找每个数的因数
{
    for(int i = 1;i<=L;i++)
    {
        for(int j = i;j<=L;j+=i)
        {
            P[j].push_back(i);
        }
    }
}
int gcd(int a, int b)//找a和b的最大公约数
{
    return b==0?a:gcd(b, a%b);
}
void solve()
{
    int n, k;
    scanf("%d%d", &n, &k);
    for(int i = 1;i<=n;i++)
        scanf("%d", &m[i]);
    printf("Case %d:", kase++);
    for(int i = 1;i<n;i++)
    {
        int x = gcd(m[i], m[i+1]);//两个相邻同学的属性值的最大公约数
        int len = P[x].size();
        if(len-k>=0)
        {
            printf(" %d", P[x][len-k]);
        }
        else
            printf(" -1");
    }
    printf("\n");
}
int main()
{

    init();
    int T;
    scanf("%d", &T);
    while(T--)
    {
        solve();
    }
    return 0;
}