神奇的结论题
首先,由于 gcd(x,y)∗lcm(x,y)=x∗y,然后有个结论小学就该知道了吧,乘积一定时,两个数差得越远和越大,所以,我们应该尽量多做这种操作。
考虑将 x,y质因数分解,设 x=p1a1⋅p2a2⋯pnan, y=p1b1⋅p2b2⋯pnbn(若某个质因子不存在就让它的指数为零)。考虑gcd和lcm的本质,则 gcd(x,y)=p1min(a1,b1)⋅p2min(a2,b2)⋯pnmin(an,bn), lcm(x,y)=p1max(a1,b1)⋅p2max(a2,b2)⋯pnmax(an,bn),然后就可以发现,每次操作过后,指数小的往小的方向移动,指数大的往大的方向移动。
所以最终的状态,应该是所有质因子按指数从小到大的顺序排列。把每个数暴力分解,sort一波就好了…
#include <bits/stdc++.h>
#define ll long long
#define fr(i,x,y) for(int i=x;i<=y;i++)
#define rf(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const int N=100001;
const int p=1e9+7;
int n;
ll a[N];
map<ll,vector<int>> mp;
template<class T> void checkmin(T &a,const T &b) { if (b<a) a=b; }
template<class T> void checkmax(T &a,const T &b) { if (b>a) a=b; }
class GCDLCM2 {
public:
int getMaximalSum( vector <int> start, vector <int> d, vector <int> cnt ) ;
};
void deco(ll &x){
int s=0;
for(ll i=2;i*i<=x;i++)
if (x%i==0){
s=0;
while(x%i==0) x/=i,s++;
mp[i].push_back(s);
}
if (x>1) mp[x].push_back(1),x=1;
}
ll power(ll a,int n){
ll ans=1;
for(ll sum=a;n;n>>=1,sum=sum*sum%p) if (n&1) ans=ans*sum%p;
return ans;
}
int GCDLCM2::getMaximalSum(vector <int> start, vector <int> d, vector <int> cnt) {
for(int i=0;i<start.size();i++)
for(int j=0;j<cnt[i];j++)
a[++n]=start[i]+1ll*j*d[i];
//fr(i,1,n) cout<<a[i]<<' ';
fr(i,1,n) deco(a[i]);
for(map<ll,vector<int>>::iterator it=mp.begin();it!=mp.end();it++){
vector<int> v=it->second;
sort(v.rbegin(),v.rend());
for(int i=0;i<v.size();i++)
a[n-i]=a[n-i]*power(it->first,v[i])%p;
//cout<<it->first<<' ';
}
ll S=0;
//cout<<endl;
fr(i,1,n) S=(S+a[i])%p;
return S;
}