HDOJ2588
计算1-N区间里有多少数和N的GCD是大于M的。
先看两个数 N = a*b,X= a*d。因为gcd ( N , X ) = a 所以b,d这两个数互质。又因为d可以是任何一个小于b的数。所以d值数量的的多少就是b的欧拉函数值。
所以,我们可以枚举a,然后去求b,然后再求b的欧拉函数值。
我们先看,我们枚举时,当i<sqrt(n),假设a=n / i, 当i>sqrt(n)之后 有b=n/i,我们观察到当n%i==0时,会出现一种情况,就是a*b==n。所以我们就可以只需要枚举sqrt(n)种情况,然后和它对应的情况就是 n/i。
我们这种枚举时间会快非常多。
#include<bits/stdc++.h>
using namespace std;
int euler(int n)
{
int res=n;
for(int i=2; i*i<=n; i++)
{
if(n%i==0)
{
res=res/i*(i-1);
while(n%i==0)
n/=i;
}
}
if(n>1)
res-=res/n;
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
int ans=0;
for(int i=1; i*i<=n; i++)
{
if(n%i==0)
{
if(i>=m)
ans+=euler(n/i); //计算sqrt(n)左边的
if(n/i>=m&&i*i!=n)
ans+=euler(i);//计算sqrt(n)右边的i*i==n时,在上个语句已经执行
}
}
printf("%d\n",ans);
}
return 0;
}
HDU3501https://vjudge.net/problem/HDU-3501
这是一道直接套板子的题,就是数据量过大,要注意模。还有就是不要忘了小于N且与N互质的所有数的和是euler(n)*n/2,这是一个性质和结论。所有小于n且与n为非互质数和=所有小于n数的和-所有小于n且与n互质的数的和
/*Problem Description
Given a positive integer N, your task is to calculate the sum
of the positive integers less than N which are not coprime to N. A is said to be coprime to B if A,
B share no common positive divisors except 1.
Input
For each test case, there is a line containing
a positive integer N(1 ≤ N ≤ 1000000000). A line containing a single 0 follows the last test case.
Output
For each test case, you should print the sum module 1000000007 in a line.
Sample Input
3
4
0
Sample Output
0
2*/
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1000000007;
ll euler(ll 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=a/i;
}
if(a>1)
res=res/a*(a-1)%mod;
return res;
}
int main()
{
ll n;
while(scanf("%lld",&n)!=EOF&&n)
{
ll sum=n*(n-1)/2;
ll ans=euler(n)*n/2;
// cout<<euler(n)<<endl;
ll an=(sum-ans)%mod;
printf("%d\n",an);
}
return 0;
}