hdu2588+3501【欧拉函数】

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

 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
0
Sample 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
3
1 1
10 2
10000 72
Sample 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;
}
可以,贴完代码的这一瞬见断了电。。。。。。。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值