列表

详情


NC24905. Parco_Love_GCD

描述

众所周知,在算法竞赛中,出题人对他出的题的难度往往存在错误的估计。比如出题人本想出个中等题,没想到却出成了简单题;本想出个自闭题,结果数据太水变成了签到题。因此,为了让一场比赛能有良好的体验,有一个靠谱的验题人是非常重要的。

CC出好题目后,便拿给小马哥看。不出所料,这些题目小马哥全都是看一眼就会做了。而且,小马哥觉得这些题对于参赛选手来说也太水了(5个签到题哦~)。为了避免发生全场十几个队AK这种紧急事态,小马哥决定把一道签到题改成简单题,于是便有了现在这个题目。

小马哥非常喜欢数论,尤其钟爱“最大公约数”(Greatest Common Divisor,简称GCD)这一概念,因此他打算出一道和GCD有关的题目。小马哥首先给出了含n个正整数的序列,然后让你考虑该序列的所有子区间的数对应的GCD值,也就是说考虑所有的值。显然,这样的值一共有个。一个中二出题人可能会让你求这数中第k大的数,但幸运的是,小马哥是个正经出题人,因此它只让你求这个数之和模的结果。

也就是要求下面这个式子:


小马哥在此预祝大家AK~

输入描述

第一行是一个整数,表示数的个数。

接下来一行给出n个整数,其中第i个整数a_i满足

输出描述

输出一行一个整数,表示ans的值。

示例1

输入:

5
16 4 7 21 3

输出:

72

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 326ms, 内存消耗: 2424K, 提交时间: 2019-04-13 14:20:41

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans,mod=1e9+7;
int a[500005];
int main(){
	int n,g;
	scanf("%d%d",&n,&a[1]);
	g=a[1];
	for(int i=2;i<=n;i++){
		scanf("%d",&a[i]);
		if(g!=1)g=__gcd(g,a[i]);
	}
	for(int i=1;i<n;i++){
		int t=a[i],j;
		ans=(ans+a[i])%mod;
		for(j=i+1;j<=n;j++){
			t=__gcd(t,a[j]);
			ans+=t;
			if(t==g)break;
		}
		if(j<n)ans+=1ll*g*(n-j);
	}
	printf("%lld\n",(ans+a[n])%mod);
    return 0;
}

C 解法, 执行用时: 268ms, 内存消耗: 12056K, 提交时间: 2022-05-18 21:30:34

#include<stdio.h>
#define ll long long
#define N 1000010
#define P 1000000007;
ll n,i,j,ans,a[N],l[N],v[N];
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int main()
{
  scanf("%lld",&n);
  for(i=1;i<=n;i++)scanf("%lld",&a[i]);
  for(i=1;i<=n;i++)
  for(v[i]=a[i],j=l[i]=i;j;j=l[j]-1)
  {
    v[j]=gcd(v[j],a[i]);
    while(l[j]>1&&gcd(a[i],v[l[j]-1])==gcd(a[i],v[j]))l[j]=l[l[j]-1];
    ans=(v[j]*(j-l[j]+1)+ans)%P;
  }
  printf("%lld",ans);
}

C++11(clang++ 3.9) 解法, 执行用时: 317ms, 内存消耗: 9556K, 提交时间: 2019-04-18 18:41:39

#include<bits/stdc++.h>
const int N=500010,P=1000000007;
int n,i,j,ans,a[N],l[N],v[N];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main(){
  scanf("%d",&n);
  for(i=1;i<=n;i++)scanf("%d",&a[i]);
  for(i=1;i<=n;i++)for(v[i]=a[i],j=l[i]=i;j;j=l[j]-1){
    v[j]=gcd(v[j],a[i]);
    while(l[j]>1&&gcd(a[i],v[l[j]-1])==gcd(a[i],v[j]))l[j]=l[l[j]-1];
    ans=(1LL*v[j]*(j-l[j]+1)+ans)%P;
  }
  printf("%d",ans);
}

上一题