ACM-ICPC 2018 焦作赛区网络预赛 G Give Candies(大数求模,快速幂,欧拉降幂)

There are NN children in kindergarten. Miss Li bought them NN candies. To make the process more interesting, Miss Li comes up with the rule: All the children line up according to their student number (1...N)(1...N), and each time a child is invited, Miss Li randomly gives him some candies (at least one). The process goes on until there is no candy. Miss Li wants to know how many possible different distribution results are there.

Input

The first line contains an integer TT, the number of test case.

The next TT lines, each contains an integer NN.

1 \le T \le 1001≤T≤100

1 \le N \le 10^{100000}1≤N≤10100000

Output

For each test case output the number of possible results (mod 1000000007).

样例输入复制

1
4

样例输出复制

8

题目来源

ACM-ICPC 2018 焦作赛区网络预赛

#include "bits/stdc++.h"
typedef long long LL;
const int maxn=1e6+5;
using namespace std;
#define rep(i,j,k) for(int i=j;i<k;i++)
LL ol(LL x)//欧拉定理:降幂定理, 
{//该函数用来返回与x在(1,x-1)中互质的个数 
	int res=x;
	for(int i=2;i*i<=x;i++)
	{
		if(x%i==0)
		{
			res=res-res/i;
			while(x%i==0)
			{
				x/=i;
			}
		}
		if(x>1)
		res=res-res/x;
	}
	return res;
}
LL q(LL x,LL y,LL MOD)//快速幂算法 
{
	LL res=1;
	while(y)
	{
		if(y%2)
			res=res*x%MOD;
		x=x*x%MOD;
		y/=2;
	}
	return res;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		char m[maxn];
		LL mod=1e9+7;
		scanf("%s",m);
		int count=1;
		while(m[strlen(m)-count]==0)
		{
			count++;
		}
		m[strlen(m)-count]--;
		LL res=ol(mod);
		LL a=0;
//最操蛋的事情就是这个a了,由于疏忽使用的是int a,导致修了一个小时的bug才ac,超难受的
//以后大数一定要注意定义为long long
		rep(i,0,strlen(m))
		{
			a=(a*10+m[i]-'0')%res;
		}
		a+=res;//注意定义要定义成LL,在大整数中 
		LL ans=q(2,a,mod); 
		cout<<ans<<endl;
	}
	return 0;
}

注意:

简单来说:就是求2的n-1次方对1e9+7求模;

设计算法:大数求模,快速幂,欧拉降幂

快速幂算法:

求解a^b%mod,返回值即为答案

LL mod_pow(LL a,LL b,LL mod)
{
	int res=1;
	while(b>0)
	{
		if(b&1) res=res*a%mod;//如果是奇数,则运行 
		a=a*a%mod;
		b>>=1; 
	}
	return res;
}
//上下两个算法实现一样功能,算法复杂度均为log(n)
LL mod_pow(LL a,LL b,LL mod)
{
	if(b==0) return 1;
	LL res=mod_pow(a*a%mod,b/2,mod);
	if(b&1) res=res*a%mod;
	return res;
}

 

a的b次方余c,然而b是一个超大整数,远远大于long long 的表示范围,但是你用大整数乘法也做不了,

因为要取模。。。。呢就直接切入正题好了,既然幂次很大,呢肯定是要降幂了,其实做这道题你就能想到

肯定有一种降幂公式,因为要用到欧拉函数,呢这里就讲一下欧拉函数的具体概念及其求法好了。。。

 

 

欧拉函数是指:对于一个正整数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)。

降幂公式:    (降幂公式中 phi() 为欧拉函数)

凌晨2点于南昌航空大学3栋405完成!

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值