首页 > 代码库 > HDU2879 HeHe 数论积性函数

HDU2879 HeHe 数论积性函数

题目名字有点搓,做题时没做出来,学长他们做出了,发现跟网上题解的思路没太大区别,网上所有题解的分析也都转自同一个地方,看样子这道题目不是那么好想的,没办法按照解析画了半天,计算器按了半天,理解了,自己敲出来了,觉得值得留念,打算再刷几道这样的


转自:http://blog.csdn.net/kksleric/article/details/8096914

定义对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数。若对于某积性函数 f(n) ,就算a, b不互质,也有f(ab)=f(a)f(b),则称它为完全积性

性质:积性函数的值完全由质数的幂决定

常见积性函数:

   φ(n) 欧拉函数,计算与n互质的正整数之数目 

 μ(n) 莫比乌斯函数,关于非平方数的质因子数目

 gcd(n,k) -最大公因子,当k固定的情况 

 d(n) n的正因子数目 

 σ(n) n的所有正因子之和 

 σk(n) - 因子函数,n的所有正因子的k之和,当中k可为任何复数。 

 Idk(n) -幂函数,对于任何复数、实数k,定义为Idk(n) = n^k (完全积性) 

 λ(n) -刘维尔函数,关于能整除n的质因子的数目 

 γ(n),定义为γ(n)=(-1)^ω(n),在此加性函数ω(n)是不同能整除n的质数的数目 


hdu 2879 HeHe

题意:In the equation X^2≡X(mod N) where x∈[0,N-1], we define He[N] as the number of solutions.
And furthermore, define HeHe[N]=He[1]*……*He[N]
Now here is the problem, write a program, output HeHe[N] modulo M for a given pair N, M.

证明转自http://www.fengshuxin.com/number_theory_hdu_2879.html

1.证明p是素数时He[p]=2.     

 x^2=x(mod p)—->p|x(x-1).因为x<p所以p不整除x也不整除x-1.所以成立的情况下是x=1或者x=0.

He[p^k]=2,证明类似上面的

2.证明对于不同的两个素数p和q,He[p*q]=4=He[p]*He[q];

首先x=0和x=1是肯定成立的,

现在由x^2=x(mod p*q)

       —>p*q|x(x-1)

     假设x=k*p[k<q]

     ——>p*q|k*p(k*p-1)

    ——->q|k(k*p-1)

   ——->q|(k*p-1)  因为k<q  q是素数 所以gcd(k,q)=1

  ——->k*p+t*q=1

 这里就变成了这个方程的解,由扩展欧几里得知,这个方程有解,但是k在[0,q-1]之内的解就一个,所以这里多一个解,同理设x=k*p又有一个解,所以x^2=x(mod p*q)有4个解(x=0 ,x=1 ,x=k*p, x=k*q)

—->He[p*q]=4=He[p]*He[q];

那么He[p1^r1*p2^r2*……*pk^rk]=2^k然后可以进一步算出HeHe只需要算n以内每个素数的倍数的个数.


#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#include<cctype>

#define ll long long

#define LL __int64

#define eps 1e-8

#define inf 0xfffffff

//const ll INF = 1ll<<61;

using namespace std;

//vector<pair<int,int> > G;
//typedef pair<int,int > P;
//vector<pair<int,int> > ::iterator iter;
//
//map<ll,int >mp;
//map<ll,int >::iterator p;

const int N = 10000000 + 5;

bool isprime[N];

int prime[N];

void clear() {
	memset(isprime,false,sizeof(isprime));
	memset(prime,0,sizeof(prime));
}

void init()
{
	prime[0] = prime[1] = 1;
	for(int i=2;i<N;i++) {
		if(!prime[i])
			for(int j=i;j<N;j+=i)
				prime[j]++;//j为某个素数倍数的个数
	}

	prime[1] = 0;
	for(int i=2;i<N;i++)
		prime[i] += prime[i - 1];//n以内的每个素数,它的倍数也在n以内的个数之和
}

LL quick(LL a,LL b,LL m) {
	LL ans = (LL)1;
	while(b) {
		if(b&1) {
			ans =(ans * a)%m;
			b--;
		}
		b >>= 1;
		a = a * a%m;
	}
	return ans;
}

int main() {
	clear();
	init();
	int k = 1;
	LL n,m;
	int t;
	scanf("%d",&t);
	while(t--) {
		scanf("%I64d %I64d",&n,&m);
		LL ans = quick((LL)2,prime[n],m);
		printf("%I64d\n",ans);
	}
	return 0;
}