Deciphering Password HDU - 2421 数论

					**Deciphering Password**

Xiaoming has just come up with a new way for encryption, by
calculating the key from a publicly viewable number in the following
way: Let the public key N = A B, where 1 <= A, B <= 1000000, and a 0,
a 1, a 2, …, a k-1 be the factors of N, then the private key M is
calculated by summing the cube of number of factors of all ais. For
example, if A is 2 and B is 3, then N = A B = 8, a 0 = 1, a 1 = 2, a 2
= 4, a 3 = 8, so the value of M is 1 + 8 + 27 + 64 = 100. However, contrary to what Xiaoming believes, this encryption scheme is
extremely vulnerable. Can you write a program to prove it?

Input

There are multiple test cases in the input file. Each test case starts
with two integers A, and B. (1 <= A, B <= 1000000). Input ends with
End-of-File. Note: There are about 50000 test cases in the input file.
Please optimize your algorithm to ensure that it can finish within the
given time limit.

Output

For each test case, output the value of M (mod 10007) in the format as
indicated in the sample output.

Sample Input
2 2
1 1
4 7
Sample Output
Case 1: 36
Case 2: 1
Case 3: 4393

题意:给定一个A,B。 N=A^B, 求N的因子中的因子数的三次和。可能这句话说的有点绕,我们可以从题目给出的样例来解释下:
A=2
B=3
那么N=2^3=8
8的因子有:1 2 4 8
接下来是关键,我们在8的因子基础上,再次统计每个数的因子个数,1的因子数就一个,那么sum=sum+1^3 ; 同理2的因子数位2,那么sum=sum+2^3 以此类推知道遍历完8的因子。

分析:由于题目给出的A,B很大,直接计算N的话铁定炸裂。所以,我们需要用下分解定理,100=2^2 + 5^2 . 可以显然发现,每次分解都是从素数开始的,我们需要准备一个素数表,来分解做准备。

接下来,分解ok,我们需要来计算质因子的个数了,公式:(a1+1)(a2+1)…(an+1) 这里的a表示质因子的指数。不懂的可以手工验算下

质因子知道了,最后一步就是计算3次方了,如果一个一个计算,铁定TLE了,因为质因子可能会有很多,A,B取100W时,质因子数量巨大。那么怎么办呢,其实也是有公式的,三次求和公式 ((1+n)*n/2)^2 。n代表求到第几项。这里就不证明了。。。。我太弱了

本题注意点就是,可能在分解的时候,最后一个分解不彻底,什么叫不彻底呢,可能最后一个值超过素数表最大值,所以,最后如果A>1,需要质因子+1

AC代码+注释:


/*
*  计算每个因子数的立方和 
*  12 2
*  (2^2*3^1)^2   ->     2^4 * 3^2
*   4的立方和*2的立方和   225*36=8100 
*/


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int const N=1000000+100;
int const mod=10007;
int A,B,cnt;
int prime[N];
int a[N];
void cal_prime()
{
	prime[0]=1;
	prime[1]=1;
	for(int i=2;i<=sqrt(N-1);i++)
	{
		if(prime[i]==0)
		{
			a[cnt++]=i;
			for(int j=i*i;j<=N-1;j+=i)
			{
				prime[j]=1;
			}
		}
	}
}
ll counting(ll a,ll b)//a的b次
{
	ll ans=1;
	while(b>0)
	{
		if(b&1)
		{
			ans=ans*a%mod;
		}
		a=a*a%mod;
		b>>=1;
	}
	return ans%mod;
} 
int main()
{
	int k=1;
	cal_prime();
	while(~scanf("%d%d",&A,&B))
	{
		ll count=1;
		ll zhi=0;
		ll result=1;
		for(int i=0;a[i]*a[i]<=N&&i<cnt;i++)//暴力跑素数个数TLE 
		{
			ll ct=0;
			while(A%a[i]==0)//分解质因数,统计个数   8^3  ->  (2,2,2,2)^3  ->   (2^4)^3
			{
				ct++;
				A/=a[i];
			}
			count=1ll*(ct*B+1);  //计算因子个数   (a1+1)(a2+1)(a3+1).....(an+1)  a1代表质因子的指数 
			count%=mod;
			zhi=((count%mod+1)%mod)*(count%mod)/2; //计算三次和公式  ((1+n)*n/2)^2
			zhi%=mod;
			result*=(zhi%mod)*(zhi%mod);
			result%=mod;
			if(A==1)break;
		}
		if(A>1)//处理A>1的情况 最后衣一个数超过素数表最大值,那么我们也要把这个数算一次,n=3,1+8+27=36   ((1+3)*3/2)^2=36 
		{
			count=1ll*(1*B+1);
			count%=mod; 
			zhi=((count%mod+1)%mod)*(count%mod)/2;
			zhi%=mod;
			result*=(zhi%mod)*(zhi%mod);
			result%=mod;
		}
		printf("Case %d: %lld\n",k++,result%mod);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值