2020 CCPC Wannafly Winter Camp Day1H

2020 CCPC Wannafly Winter Camp Day1H

題目

7-8 1H. 最大公約數

有三個人,A,B,C,其中 A 和 B 共享了一個神祕的數字 k,已知 1≤k≤n。

現在 A 和 C 說:“k 的值等於 x”。

C 不太信任 A,於是想向 B 確認一下 k 是否真的等於 x。B 雖然不想直接把 k 的值告訴 C,但是 B 允許 C 給出一個正整數 y(注意 y 可以大於 n),然後 B 會回答 gcd(k,y)。

現在給出 k,n,你需要幫助 C 決定這樣的 y 的取值,使得 C 一定可以通過 B 的回答來判斷 A 有沒有撒謊。如果這樣的 y 有多個,你需要輸出最小的那個。

輸入格式:
輸入第一行是一個整數 T(1≤T≤50)。

對於每組數據,輸入一行兩個整數 n,k(1≤k≤n≤500)。

輸出格式
對於每組數據,輸出一行一個整數,表示答案。如果滿足條件的 y 不存在,則輸出 −1。

輸入樣例:
3
10 1
10 4
10 7

輸出樣例:
210
8
7
在這裏插入圖片描述

思路

一開始我的思路是,既然我要辨別這個數字是真是假,那麼我就要保證,我給出的y,會使得gcd(k,y)在1-n中,gcd(i, y)(1<=i<=n)中是獨一無二的,這樣我就能分辨出來,如果gcd(k, y)是獨一無二的,那麼x就會等於k,如果不是獨一無二的,x就不等於k,所以只要讓gcd(k, y)獨一無二即可,怎麼才能獨一無二,就是讓y是k的倍數,btw,首先解釋爲什麼樣例1的10 1答案是210,首先我們要一個y,使得在1-10中gcd(1,210)是獨一無二的,那麼就讓1-10中的質數相乘即可,這樣gcd(i, 210)(2<=i<=10)都不可能爲1。那麼我們只要求出1-n裏面有多少是k的倍數,那麼我們就可以把問題轉換成1,2,3…n/k中讓gcd(1, y)獨一無二,也就是讓1-n/k的質數相乘,最後再乘上k,超出範圍要用大數乘法。

代碼

#include <iostream>
#include <cstdio>
#include <set>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <sstream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <fstream>
#include <iomanip>
using namespace std;
#define dbg(x) cerr << #x " = " << x <<endl;
typedef pair<int, int> P;
typedef long long ll;

const int MAXN = 1000;
int prime[MAXN];
int tot = 0;
bool is[MAXN];
void init()
{
    memset(is, 1, sizeof(is));
    is[0] = is[1] = 0;
    for(int i = 2; i < MAXN; i++)
    {
        if(is[i])
        {
            prime[tot++] = i;
        }
        for(int j = 0; j < tot; j++)
        {
            if(prime[j] * i >= MAXN) break;
            is[i * prime[j]] = 0;
            if(i % prime[j] == 0) break;
        }
    }
}

struct BigInt
{
    const static int mod = 10000;
    const static int DLEN = 4;
    int a[600], len;
    BigInt()
    {
        memset(a, 0, sizeof(a));
        len = 1;
    }
    BigInt(int v)
    {
        memset(a, 0, sizeof(a));
        len = 0;
        do
        {
            a[len++] = v % mod;
            v/=mod;
        }while(v);
    }
    BigInt operator *(const BigInt &b)const
    {
        BigInt res;
        for(int i = 0; i < len; i++)
        {
            int up = 0;
            for(int j = 0; j < b.len; j++)
            {
                int temp = a[i]*b.a[j] + res.a[i+j] + up;
                res.a[i+j] = temp % mod;
                up = temp / mod;
            }
            if(up != 0)
            {
                res.a[i+b.len] = up;
            }
        }
        res.len = len + b.len;
        while(res.a[res.len-1] == 0 && res.len > 1) res.len--;
        return res;
    }

    void output()
    {
        printf("%d", a[len-1]);
        for(int i = len-2; i >= 0; i--)
        {
            printf("%04d", a[i]);
            
        }
        printf("\n");
    }
};

int main()
{
    
    int t, n, k;
    init();
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &k);
        int l, r;
        l = 1;
        r = n/k;
        BigInt ans(1);
        for(int i = l; i <= r; i++)
        {
            if(is[i])
            {
                BigInt tmp(i);
                ans = ans * tmp;
            }
        }
        BigInt temp(k);
        ans = ans * temp;
        ans.output();
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章