CF2134B

Problem

给你一个数组 $n$ 和一个数 $k$,让你给每个 $a_i$ 加上 $p\times k$ 这里 $0\le p\le k$,使得所有 $a_i$ 的 $\gcd$ 最小,输出一个方案。

Solution

设这个 $\gcd$ 为 $x$。首先可以证明 $\gcd(k,x)=1$,因为如果大于一,那么所有的原来的 $a_i$ 一定包含了这个 $\gcd$。

我们找到最小的 $x$,关于为什么最小的就行后面说,这里直接枚举就好了,只是找到互质的数应该不是很大,这个就不证明了。

然后我们就要计算对于 $a_i$ 要加上多少个 $k$,是 $(((x-(a_i\bmod x))\bmod x)\times inv)\bmod x$ 其中 $inv$ 是乘法逆元,这个其实就是补上 $a_i$ 使它能被 $x$ 整除。

那么怎么保证 $(((x-(a_i\bmod x))\bmod x)\times inv)\bmod x$ 一定比 $k$ 小呢,因为对 $x$ 取模了。

$k=1$ 的情况记得单独处理。

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <iomanip>
using namespace std;
using LL=long long;
LL n,k,a[100005];
LL invv(LL a, LL m)
{
    for(LL x=1;x<m;x++)
    {
        if((a*x)%m==1)
        {
            return x;
        }
    }
    return 1;
}
inline LL gcd(LL x,LL y){
    if(!y) return x;
    return gcd(y,x%y);
}
void solve(){
    LL g=2;
    cin>>n>>k;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    if(k==1)
    {
        for(int i=0;i<n;i++)
        {
            if(a[i]%2==1)
            {
                cout<<a[i]+1<<" ";
            }
            else
            {
                cout<<a[i]<<" ";
            }
        }
        cout<<endl;
        return ;
    }
    while(gcd(k,g)!=1)
    {
        g++;
    }
    LL ink=invv(k%g,g);
    for(int i=0;i<n;i++)
    {
        cout<<a[i]+((((g-a[i]%g)%g)*ink)%g)*k<<" ";
    }
    cout<<endl;
}
int main(){
    int t;
    cin>>t;
    while(t--) solve();
    return 0;
}