周中训练笔记+hdu2588+3501【欧拉函数】

来源:互联网 发布:算法导论 kindle 编辑:程序博客网 时间:2024/05/22 12:17

这俩题目都算是欧拉函数的应用极致了,直接上题目

 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.
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
340
Sample Output
02
题意:求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 longll 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.
Input
The 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.
Output
For each test case,output the answer on a single line.
Sample Input
31 110 210000 72
Sample Output
16260
题意:给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 longll 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;}
可以,贴完代码的这一瞬见断了电。。。。。。。。。。。。

原创粉丝点击