题面描述
最近,华东交通大学ACM训练基地的老阿姨被一个数学问题困扰了很久,她希望你能够帮她解决这个问题。
这个数学问题是这样的,给你一个N,要求你计算
gcd(a,b)表示a和b的最大公约数
输入描述:
多组输入,每行一个整数n(1<=n<=10^14)。
输出描述:
每行一个整数,表示答案。由于答案会很大你要对1000000007取模。
示例1
输入
4 10
输出
6 35
说明
样例一,2+4=6。 样例二,2+4+5+6+8+10=35。
以下是官方题解:
该公式相当于求 小于等于n中所有与n不互质的数的和
根据欧拉函数得知 小于或等于n的数中,与n互质的数的总和为φ(n) * n / 2 (n>1)
答案就是
1. 0 (n=1)
2 n*(n+1)/2 - φ(n) * n / 2 (n>1)
也可以找出素因子进行容斥
AC:
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("\n")
#define debug(a,b) cout<<a<<" "<<b<<" "<<endl
#define ffread(a) fastIO::read(a)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=5e5+10,inf=0x3f3f3f3f;
const ll mod=1000000007;
ll euler(ll n) //返回euler(n)
{
ll res=n,a=n;
for(ll i=2; i*i<=a; i++)
{
if(a%i==0)
{
res=res/i*(i-1);
while(a%i==0)
a/=i;
}
}
if(a>1)
res=res/a*(a-1);
return res%mod;
}
ll pow_mod(ll n,ll m)
{
ll ans = 1;
while(m > 0)
{
if(m & 1)ans = (ans * n) % mod;
m = m >> 1;
n = (n * n) % mod;
}
return ans;
}
int main()
{
ll n;
while(scanf("%lld",&n)!=EOF)
{
if(n==1)
{
printf("0\n");
continue;
}
ll inv2=pow_mod(2,mod-2);
ll temp=((n%mod)*((n+1)%mod)%mod)*inv2%mod;
ll ans=temp-(euler(n)*(n%mod)%mod*inv2)%mod;
printf("%lld\n",(ans%mod+mod)%mod);
}
return 0;
}