UESTC 1697 简单GCD问题(一) 筛法

简单GCD问题(一)

Time Limit: 1500/500MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)

秦队长给你两个长度为nn的序列AA和BB,第ii个数分别为aiai和bibi
请你求出1i,jngcd(i,j)aibj∑1≤i,j≤ngcd(i,j)aibj的值
答案可能很大,请输出模1e9+71e9+7后的结果

Input

第一行输入一个数n(1n100000)n(1≤n≤100000),表示序列长度
第二行输入nn个数,表示序列AA,第ii个数表示ai(1ai1000000)ai(1≤ai≤1000000)
第三行输入nn个数,表示序列BB,第ii个数表示bi(1bi1000000)bi(1≤bi≤1000000)

Output

输出模1e9+71e9+7后的答案

Sample input and output

Sample InputSample Output
4
1 2 3 4
1 2 3 4
186

Source

missever
 

 有点容斥的意思,类似素数筛的那种;

na跟nb表示以i为gcd,约数中含有i的所有数的和;

再枚举gcd;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define LL long long
#define pi (4*atan(1.0))
#define eps 1e-8
#define bug(x)  cout<<"bug"<<x<<endl;
const int N=3e5+10,M=2e6+10,inf=1e9+10;
const LL INF=1e18+10,mod=1e9+7;

int a[N],b[N];
LL na[N],nb[N];
LL dp[N];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j+=i)
            na[i]=(na[i]+a[j])%mod,nb[i]=(nb[i]+b[j])%mod;
    }
    LL ans=0;
    for(int i=n;i>=1;i--)
    {
        dp[i]=(1LL*na[i]*nb[i])%mod;
        for(int j=i+i;j<=n;j+=i)
            dp[i]=(dp[i]-dp[j]+mod)%mod;
        ans=(ans+((dp[i]*i)%mod))%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2017-07-23 19:52  jhz033  阅读(250)  评论(0编辑  收藏  举报