Parco_Love_GCD
链接:https://ac.nowcoder.com/acm/contest/625/H
题目描述
众所周知,在算法竞赛中,出题人对他出的题的难度往往存在错误的估计。比如出题人本想出个中等题,没想到却出成了简单题;本想出个自闭题,结果数据太水变成了签到题。因此,为了让一场比赛能有良好的体验,有一个靠谱的验题人是非常重要的。
CC出好题目后,便拿给小马哥看。不出所料,这些题目小马哥全都是看一眼就会做了。而且,小马哥觉得这些题对于参赛选手来说也太水了(5个签到题哦~)。为了避免发生全场十几个队AK这种紧急事态,小马哥决定把一道签到题改成简单题,于是便有了现在这个题目。
小马哥非常喜欢数论,尤其钟爱“最大公约数”(Greatest Common Divisor,简称GCD)这一概念,因此他打算出一道和GCD有关的题目。小马哥首先给出了含n个正整数的序列a1,a2,⋯,an,然后让你考虑该序列的所有子区间的数对应的GCD值,也就是说考虑所有gcd(al,⋯,ar)gcd(al,⋯,ar)的值。显然,这样的值一共有n(n+1)2n(n+1)2个。一个中二出题人可能会让你求这n(n+1)
2n(n+1)2数中第k大的数,但幸运的是,小马哥是个正经出题人,因此它只让你求这n(n+1)2n(n+1)2个数之和模109+7109+7的结果。也就是要求下面这个式子:ans=(∑nl=1∑nr=lgcd(al,⋯,ar))mod(109+7)ans=(∑l=1n∑r=lngcd(al,⋯,ar))mod(109+7)
小马哥在此预祝大家AK~
输入描述:
第一行是一个整数
n(1≤n≤5×105)n (1≤n≤5×105),表示数的个数。接下来一行给出n个整数,其中第i个整数ai,ai满足1≤ai≤10^9,1≤ ai ≤10^9。
示例1
输入
5
16 4 7 21 3
输出
72
显然:
gcd(a,b,c)=gcd(a,gcd(b,c))
a1,a2,a3…… 中有一个数是1的时候,gcd=1
a1,a2,a3…… 中有一个数是最小公因数min_yue的时候,gcd=min_yue
只要ai=min_yue,gcd=ai。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;//不用ll就是过不了。
const ll mod=1e9+7;
ll k[500005];
ll gcd(ll x,ll y){
return x?gcd(y%x,x):y;
}
int main() {
//freopen("in.txt","r",stdin);
int n;
scanf("%d",&n);
ll min_yue;//这组数的最小公约数
for(int i=0; i<n; i++) {
scanf("%lld",&k[i]);
if(i==0)
min_yue=k[i];
else if(min_yue!=1)//等于1的时候就不用算了
min_yue=gcd(min_yue,k[i]);
}
ll ans=0;
ll pre;
for(int i=0; i<n; i++) {
pre=k[i];
for(int j=i; j<n; j++) {
pre=gcd(pre,k[j]);
if(pre==min_yue) {//如果等于最小公约数,后面有n-j个数,都等于min_yue
ans=(ans+(n-j)*min_yue)%mod;
break;
}
ans=(ans+pre)%mod;
}
}
printf("%lld",ans%mod);
return 0;
}
时间 内存
423ms 9312k
转载自已通过大佬