欧拉

欧拉函数

  • 定义:
    ϕ(i)表示第i个欧拉函数的值,代表了从1到i与i互质的数的个数,例如ϕ(8)=4 因为1,3,5,7均和8互质
  • 通式 :
  • 一些性质
    1,如果x是质数则 ϕ(x)=x-1;
    2,如果a是质数不是n的因子则 ϕ(an)=ϕ(n)(a-1);进一步推如果n是奇数则ϕ(2n)=ϕ(n);
    3,如果a是n的质因子则 ϕ(a
    n)=ϕ(n)a;
    4,如果n和m互质 则 ϕ(n
    m)= ϕ(n)*ϕ(m);
    5,如果n>2则 ϕ(n)一定是偶数
    6,如果p是质数 则 ϕ(pq)=pq-pq-1;

写一下欧拉函数 时间复杂度是O(根n);

//欧拉定理 时间复杂度是O(根n) 
int phi(int n){
	int sum=n;
	for(int i=2;i*i<=n;i++)
	{
		if(n%i==0){
			sum=sum/i*(i-1);//找到质因数然后 
			//sum=sum-sum/i;与上面的等价
			while(n%i==0){
				n=n/i;
			} 
		}
	}
	if(n>1) sum=sum/n*(n-1);//模拟欧拉等于x=x*(1-1/a);x是这个数 a 是x的质因数 ; 
	return sum;
} 

写一个大数的欧拉函数,其实就是利用欧拉筛法,时间复杂度O(N)


//O(n) 利用线性筛法 处理1-n的 
const int maxn=1e6+7;
bool flag[maxn];
ll phi[maxn],p[maxn],cnt;
void get_phi()//线性筛
{
	phi[1]=1;
	for(int i=2;i<maxn;i++){
		if(flag[i]==0){
			p[++cnt]=i;
			phi[i]=i-1;//性质1 
		}
		for(int j=1;j<=cnt&&i*p[j]<maxn;j++){
			flag[i*p[j]]=1;
			if(i%p[j]==0){
				phi[i*p[j]]=phi[j]*p[i];//性质3; 
				break;
			}
			else phi[i*p[j]]=phi[j]*(p[i]-1);//性质2
		}
	}
}
int get__phi(int n){//求大于maxn的欧拉值 
	int now =1;
	for(int i=1;i<=cnt ;i++)
	{
		if(n<maxn) return now*phi[n];//小于maxn直接可以得到 
		if(n%p[i]==0) while(1){//如果p[i]是n的质因数利用性质 
			n/=p[i];
			if(n%p[i]==0)//性质三
			now*=p[i];
			else //性质二 
			{
				now*=p[i]-1;
				break;// 下一个p[i]无法被整除退出 
			}
			 
		}
		if(n==1) return now*phi[n];//就是n已经没有质因子了
		if(p[i]>sqrt(t)){//就是说明这个数是质数 
			return now*(n-1);
		} 
	}
} 

—————————————————————————————————————————————————————

欧拉定理:

就是欧拉函数的一个分支,

  • aϕ(m)=1(modm)(a,m互质);
    —————————————————————————————————————————————————————

欧拉降幂

  • 在大数取余中常用
  • 原理很简单,就是 at%m;其中t=k*ϕ(m)+r;
    所以式子可以化成aϕ(m)*k *ar%m;
    由欧拉函数得 aϕ(m)%m==1;
    所以aϕ(m)*k ar%m=1ar%m;
    这就简化了很多不必要的计算;
  • 所以我们可以推出
    • 欧拉降幂在a与m互质情况下的公式:
      aq=aq%ϕ(m)(mod m);
    • 当然还有通用公式(不管是否互质):
      当q大于ϕ(m)时: aq=aq%ϕ(m)+ϕ(m)(mod m);
      可以去做做 洛谷上的板子题P5091

威尔逊定理

其实威尔逊定理也就是一个式子,很简单的。

当为素数是:
(n−1)!≡−1(modn)
或者是
(n−2)!≡1(modn)

剩下的也不多说哦,加上连个例题吧;
(1)HDU5391

A - Zball in Tina Town

Tina Town is a friendly place. People there care about each other.
Tina has a ball called zball. Zball is magic. It grows larger every day. On the first day, it becomes 1 time as large as its original size. On the second day,it will become 2 times as large as the size on the first day. On the n-th day,it will become n times as large as the size on the (n-1)-th day. Tina want to know its size on the (n-1)-th day modulo n.

  • Input
    The first line of input contains an integer T, representing the number of cases.
    The following T lines, each line contains an integer n, according to the description.
    T≤105,2≤n≤109

  • Output
    For each test case, output an integer representing the answer.

  • Sample Input
    2
    3
    10

  • Sample Output
    2
    0

  • 思路分析 就是个简单的运用威尔逊定理

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxn=2e6+1010;
#define inf 0x3f3f3f3f
const int mod=1e9+7;

ll f[maxn],a[maxn],b[maxn],n,m,t,flag,temp,sum,x,y;
string str,s;
ll dp[100][100];

int main () {
	cin>>t;
	while(t--) {
		cin>>n;
		ll k=0;
		if(n==2) k=0;
		else if(n%2==0) k=1;
		else {//这个素数判定的地方会卡一下时间
			for(int i=3; i*i<=n; i+=2)
				if(n%i==0) {
					k=1;
					break;
				}
		}
		if(n == 4) cout<<2<<endl;
		else if(k==0) cout<<(n-1)<<endl;
		else cout<<0<<endl;
	}

	return 0;
}

(2)HDU2973

B - YAPTCHA

  • The math department has been having problems lately. Due to immense amount of unsolicited automated programs which were crawling across their pages, they decided to put Yet-Another-Public-Turing-Test-to-Tell-Computers-and-Humans-Apart on their webpages. In short, to get access to their scientific papers, one have to prove yourself eligible and worthy, i.e. solve a mathematic riddle.

    However, the test turned out difficult for some math PhD students and even for some professors. Therefore, the math department wants to write a helper program which solves this task (it is not irrational, as they are going to make money on selling the program).

    The task that is presented to anyone visiting the start page of the math department is as follows: given a natural n, compute


where [x] denotes the largest integer not greater than x.

  • Input
    The first line contains the number of queries t (t <= 106). Each query consist of one natural number n (1 <= n <= 106).
  • Output
    For each n given in the input output the value of Sn.
  • Sample Input
    13
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    100
    1000
    10000
  • Sample Output
    0
    1
    1
    2
    2
    2
    2
    3
    3
    4
    28
    207
    1609
  • 思路分析 上个题是直接判断n 这个是判断3*n+7其实也一样,只不过这个用到了前缀和,而且这个题会卡你内存就是bool和int这样子的
    具体解释可以参照orz的博客
    代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxn=3e6+1010;
#define inf 0x3f3f3f3f
const int mod=1e9+7;

ll f[maxn],n,m,t,flag,temp,sum,x,y;
bool a[maxn];//这个地方要用bool 不能用int 否则会内存超限,原因很简单,bool占的字节少 

void find(ll n){
	ll cnt=0;
	n=n*3+7;
	a[1]=1;
	for(int i = 2; i <= n;i++)
	{
		if(!a[i]) f[++cnt] = i;
		for(int j = 1; j<=cnt&&i*f[j]<=n ;j++)
		{
			a[i*f[j]]=1;
			if(i%f[j]==0) break;
		}
	}
}

void pp(ll n){
	//3*k+7素数为1 合数为0
	memset(f,0,sizeof(f));
	for(int i = 1;i <= n;i++)
	{
		if(!a[3*i+7]){
			f[i]=f[i-1]+1;
		}	
		else f[i]=f[i-1];
	}
}
int main(){
	find(1e6+7);
	pp(1e6+7);
	cin>>t;
	while(t--){
		cin>>n;
		cout<<f[n]<<endl;
	}
	return 0;
}