DAY-3

专题:简单数论

我今天一定是学数学来的。学完我觉得我都可以参加数学竞赛了。晕头转向,哪哪都没学过。

Question_A

    考察欧拉函数,打表打表!!!

    普通打表太慢了,要用什么筛法,我学了学百度百科的打表方法,感觉好神奇哦,直接使用了三个性质没有套用求解公式,那样循环居然每个数都能走一遍(而且那个素数判断也镶嵌在其中太神奇了吧),但感觉有的会重复计算;然后还看了看其他人的打表方法大部分都用了那个公式,也是筛法;迷……

     欧拉函数是指:对于一个正整数n,小于n且和n互质的正整数(包括1)的个数,记作φ(n) 。

     通式:φ(x)=x*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)…..(1-1/pn),其中p1, p2……pn为x的所有质因数,x是不为0的整数。φ(1)=1        (唯       一和1互质的数就是1本身)。

    对于质数p,φ(p) = p - 1。注意φ(1)=1.

    欧拉定理:对于互质的正整数a和n,有aφ(n) ≡ 1 mod n。

    欧拉函数是积性函数——若m,n互质,φ(mn)=φ(m)φ(n)。 

     若n是质数p的k次幂,φ(n)=p^k-p^(k-1)=(p-1)p^(k-1),因为除了p的倍数外,其他数都跟n互质。

    特殊性质:当n为奇数时,φ(2n)=φ(n)

    欧拉函数还有这样的性质:

    设a为N的质因数,若(N % a == 0 && (N / a) % a == 0) 则有E(N)=E(N / a) * a;若(N % a == 0 && (N / a) % a != 0) 则有:E         (N) =      E(N / a) * (a - 1)。

    参考链接:www.cnblogs.com/soTired/p/4764321.html

    附:百度百科上的打表模板:

/*
特性 :
1.若a为质数,phi[a]=a-1;
2.若a为质数,b mod a=0,phi[a*b]=phi[b]*a
3.若a,b互质,phi[a*b]=phi[a]*phi[b](当a为质数时,if b mod a!=0 ,phi[a*b]=phi[a]*phi[b])
*/
int m[n],phi[n],p[n],nump;
//m[i]标记i是否为素数,0为素数,1不为素数;p是存放素数的数组;nump是当前素数个数;phi[i]为欧拉函数
int make()
{
        phi[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (!m[i])//i为素数
        {
            p[++nump]=i;//将i加入素数数组p中
            phi[i]=i-1;//因为i是素数,由特性得知    
        }    
        for (int j=1;j<=nump&&p[j]*i<n;j++)  //用当前已的到的素数数组p筛,筛去p[j]*i
        {
            m[p[j]*i]=1;//可以确定i*p[j]不是素数 
            if (i%p[j]==0) //看p[j]是否是i的约数,因为素数p[j],等于判断i和p[j]是否互质 
            {
                phi[p[j]*i]=phi[i]*p[j]; //特性2
                break;
            }
            else phi[p[j]*i]=phi[i]*(p[j]-1); //互质,特性3其,p[j]-1就是phi[p[j]]   
        }
    }
}

  

Question_B

    你敢相信么我题意看不懂,什么是约数、还是叫因数。。查了半天。  直接看定义比较明了;

    1)一个正整数n按素因子分解:n=p1^a1*p2^a2*....*pk^ak,那么n的约数的个数为(a1+1)(a2+1)...(ak+1);

    2)对于一个素数p,n!中按素因子分解,p的幂为 n/p+n/p^2+n/p^3...,其中/为整除

    3)C(N,K)=N! / (K! (N-K)!)       整体约数个数f(N!) - f(K!) - f((N-K)!).

    还有就是,cout 输出时间和 printf 怎么差这么多,前者450ms,后者625ms。

    本题上代码,因为太多知识点了

#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int primes[341];
int numpr;

bool jupr(int n){
	for(int i=2;i*i<=n;i++)
	    if(n%i==0)
                return false;
	return true;
}

void prime(){
	for(int i=2;i<=432;i++)
		if(jupr(i))
			primes[numpr++]=i;
}

int cal(int a,int b){
	int sum=0;
	int flag=b;
	while(a>=b){
	    sum+=a/b;
	    b*=flag;
	}
	return sum;
}

int main(){
	prime();
	int n,k;
	while(~scanf("%d%d",&n,&k)){
		long long ans=1;
		for(int i=0;i<numpr&&primes[i]<=max(n,k);i++){
		    int a = cal(n,primes[i]);
                    int b = cal(k,primes[i]);
                    int c = cal(n-k,primes[i]);
                    ans*=(a-b-c+1);
		}
		printf("%lld\n",ans);
	}
}

Question_C

    什么积性函数性质啊,不会,只学会了最弱鸡的方法,欧拉啊欧拉,wuwuwu。

    欧拉函数 φ(x)φ(x) :1到x-1有几个和x互质的数。

    gcd(i,n)必定是n的一个约数。

    若p是n的约数,那么gcd(i,n)==p的有φ(n/p)φ(n/p)个数,因为要使gcd(i,n)==p,i/p和n/p必须是互质的。

    那么就是求i/p和n/p互质的i在[1,n]里有几个,就等价于 1/p,2/p,...,n/p 里面有几个和n/p互质,即φ(n/p)。

    求和的话,约数为p的有φ(n/p),所以就是p*φ(n/p),同时把约数为n/p的加上去,i*i==n特判一下。

    参考链接:https://www.cnblogs.com/flipped/p/5690123.html

    太难了吧这也.......

#include<cstdio>
#include<cmath>
long long eular(int x){
	int rea=x;
	for(int i=2;i<=sqrt(x);i++){
		if(x%i==0){
			rea=rea/i*(i-1);
			while(x%i==0)
				x=x/i;
		}
	}
	if(x>1)
		rea=rea/x*(x-1);
	return rea;
}

int main(){
	long long n;
	while(~scanf("%lld",&n)){
		long long ans=0;
		long long i;
		for( i=1;i<sqrt(n);i++){
			if(n%i==0)
				ans+=i*eular(n/i)+n/i * eular(i);
		}
		if(i*i==n)
			ans+=i*eular(i);
		printf("%lld\n",ans);
	}
}

    后来看了看积性性质大概就公式吧 ,没太懂:f(n)=n*∏(1+ai*(pi-1)/pi

#include <iostream>
using namespace std;
typedef long long ll;
 
int main()
{
	ll n;
	while(scanf("%lld",&n)==1){
		ll ans=n;
		for(ll i=2;i*i<=n;++i){
			if(n%i==0){
				ll a=0,p=i;
				while(n%p==0){
					++a;
					n/=p;
				}
				ans=ans+ans*a*(p-1)/p;
			} 
		}
		if(n!=1)
			ans=ans+ans*(n-1)/n;
		printf("%I64d\n",ans);
	}	
	return 0;	
}

   。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

Question_E

    欧几里德算法又称辗转相除法,是指用于计算两个正整数a,b的最大公约数。应用领域有数学和计算机两个方面。计算公式gcd(a,b) = gcd(b,a mod b)。

    转化为gcd(b×t+a,b)=gcd(a,b)(t为任意整数)

    刚开始一直 Runtime Error  ,   (sum-1)的值没把握好。

猜你喜欢

转载自blog.csdn.net/explormt/article/details/81388459