这俩题目都算是欧拉函数的应用极致了,直接上题目
Calculation 2
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.
InputFor 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.OutputFor each test case, you should print the sum module 1000000007 in a line.Sample Input
3 4 0Sample Output
0 2题意:求1-n之间与n不互质的数的和
思路:暴力求解是行不通的,欧拉函数是求与n互质的数的个数,如何求和是个问题
先给出和的公式:sum(n)=n/2*phi[n]
九章算术里的更相减损法 ↓↓↓↓↓↓↓
简略的证明一下:gcd(n,k)=gcd(k,n-k);
使k<n并且gcd(n,k)==1,所以存在gcd(n,n-k)也为1,所以小于n的范围为之内,出现k和n-k两组,求所有k的和,即(n/2)*phi[n]
盖提只需要求出1-n的和来,减去与n互质的数的和即可,最后要mod1000000007
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
using namespace std;
#define mod 1000000007
#define ll long long
ll get_phi(ll n)
{
ll ans=n;
for(int i=2;i<=(double)sqrt(n*1.0);i++)
{
if(n%i==0)
ans=ans*(1.0-1.0/i);
while(n%i==0)
n=n/i;
}
if(n>1)
ans=ans*(1.0-1.0/n);
return ans;
}
int main()
{
ll n;
while(cin>>n)
{
if(n==0)
break;
ll sum=(n-1)*n/2;
ll ans=sum-get_phi(n)*n/2;
cout<<ans%mod<<endl;
}
return 0;
}
GCD
The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes written (a,b),is the largest divisor common to a and b,For example,(1,2)=1,(12,18)=6.
(a,b) can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.
InputThe first line of input is an integer T(T<=100) representing the number of test cases. The following T lines each contains two numbers N and M (2<=N<=1000000000, 1<=M<=N), representing a test case.OutputFor each test case,output the answer on a single line.Sample Input
(a,b) can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.
3 1 1 10 2 10000 72Sample Output
1 6 260题意:给n和m,x是1-n之间的数,问你gcd(x,n)>=m的数有多少
思路:刚开始是想从m开始,找到第一个gcd(x,n)>=m的数,然后筛去他的倍数,标记,重复此操作,但是数据太大,不好实现标记
欧拉函数又发挥了
如果m是1,那么所有的<=n都满足条件直接出n
m不是1,现x<=n,那假设n=p*d,x=q*d,且gcd(x,n)==d,所以p,q互质,那么现在问题转化成了找p使得p*d==n并且d>=m的个数
首先p是n的因子,这个坑的地方就在于n=p*p的时候,留意不要多加
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
using namespace std;
#define mod 1000000007
#define ll long long
ll get_phi(ll n)
{
ll ans=n;
for(int i=2;i<=(double)sqrt(n*1.0);i++)
{
if(n%i==0)
ans=ans*(1.0-1.0/i);
while(n%i==0)
n=n/i;
}
if(n>1)
ans=ans*(1.0-1.0/n);
return ans;
}
int main()
{
int t;
cin>>t;
ll n,m;
while(t--)
{
cin>>n>>m;
ll ans=0;
if(ans==1)
{
cout<<get_phi(n)<<endl;
}
else
{
for(ll i=1;i<=sqrt(n);i++)
{
if(n%i==0)
{
if(i>=m)
ans+=get_phi(n/i);
if(i*i!=n&&n/i>=m)
ans+=get_phi(i);
}
}
cout<<ans<<endl;
}
}
return 0;
}
可以,贴完代码的这一瞬见断了电。。。。。。。。。。。。