[绝对能看懂!]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 a0, a1, a2, …, ak-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, a0 = 1, a1 = 2, a2 = 4, a3 = 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?

输入

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.

输出

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

提示

2008 Asia Hangzhou Regional Contest Online.

分析

给定A,B,求 N = A B N=A^B N=AB的各个因子的因子个数的立方和。比较拗口,用公式叙述。设N的因子为 a 1 , a 2 , . . . , a k a_1,a_2,...,a_k a1,a2,...,ak,对于任意 a i ( 1 ≤ i ≤ k ) a_i (1\leq i\leq k) ai(1ik),求 a i a_i ai的因子个数 ,然后求得最终结果 M = ∑ i = 0 k n M=\sum_{i=0}^{k}n M=i=0kn,输出结果取余10007。
定义1:函数 d ( a ) d(a) d(a) a a a的因子个数。例如,4的因子个数为3个,分别是1,2,4,则 d ( 4 ) = 3 d(4)=3 d(4)=3
定义2:函数 D ( N ) D(N) D(N) N N N的各个因子的立方和,即 D ( N ) = ∑ m ∣ N m 3 D(N)=\sum_{m|N}m^3 D(N)=mNm3
引理1 d ( a ) d(a) d(a) D ( N ) D(N) D(N)是积性函数(multiplicative function)。事实上两者是除数函数(divisor function)的两种特殊情况,而除数函数是积性函数。积性函数 f ( x ) f(x) f(x)具有如下性质:
(1) f ( 1 ) = 1 f(1)=1 f(1)=1
(2) f ( a ⋅ b ) = f ( a ) ⋅ f ( b ) f(a\cdot b)=f(a)\cdot f(b) f(ab)=f(a)f(b),当且仅当a,b互质
满足上面两条性质,那么我们说 f ( x ) f(x) f(x)是积性函数。
引理2:积性函数的除数函数还是积性函数。
证明(可略过):
{
假设 f ( x ) f(x) f(x)是积性函数,令 D ( f ) D(f) D(f) f f f的除数函数。假设 ( m , n ) = 1 (m,n)=1 (m,n)=1(即m,n互质),则有:
[ D ( f ) ] ( m ) = ∑ a ∣ m f ( a ) a n d [ D ( f ) ] ( n ) = ∑ b ∣ n f ( b ) [D(f)](m)=\sum_{a|m}f(a) \quad and \quad [D(f)](n)=\sum_{b|n}f(b) [D(f)](m)=amf(a)and[D(f)](n)=bnf(b)
即:
[ D ( f ) ] ( m ) ⋅ [ D ( f ) ] ( n ) = ( ∑ a ∣ m f ( a ) ) ( ∑ b ∣ n f ( b ) ) = ∑ a ∣ m ∑ b ∣ n f ( a ) f ( b ) [D(f)](m)\cdot [D(f)](n)=\left( \sum_{a|m}f(a)\right)\left( \sum_{b|n}f(b)\right) =\sum_{a|m} \sum_{b|n} f(a)f(b) [D(f)](m)[D(f)](n)=amf(a)bnf(b)=ambnf(a)f(b)
由于 ( m , n ) = 1 (m,n)=1 (m,n)=1 a ∣ m a|m am b ∣ n b|n bn,故 ( a , b ) = 1 (a,b)=1 (a,b)=1(证明略,高代基础)。因此由 f ( x ) f(x) f(x)为积性函数可得:
[ D ( f ) ] ( m ) ⋅ [ D ( f ) ] ( n ) = ∑ a ∣ m ∑ b ∣ n f ( a b ) [D(f)](m)\cdot [D(f)](n)=\sum_{a|m} \sum_{b|n} f(ab) [D(f)](m)[D(f)](n)=ambnf(ab)
对于 m n mn mn的任意一个因子,我们都可以将其写作 d = a b d=ab d=ab其中 a ∣ m a|m am b ∣ n b|n bn。故:
[ D ( f ) ] ( m ) ⋅ [ D ( f ) ] ( n ) = [ D ( f ) ] ( m ⋅ n ) [D(f)](m)\cdot [D(f)](n)=[D(f)](m\cdot n) [D(f)](m)[D(f)](n)=[D(f)](mn)
得证 D ( f ) D(f) D(f)为积性函数。
参考:
http://sites.millersville.edu/bikenaga/number-theory/divisor-functions/divisor-functions.html
}

正式解题:

题目要我们求的其实就是 [ D ( d ) ] ( N ) = ∑ a ∣ N d ( a ) [D(d)](N)=\sum_{a|N}d(a) [D(d)](N)=aNd(a), d ( a ) d(a) d(a)是a的因子个数。由引理2可知该函数为积性函数,且 N = A B N=A^B N=AB,由于积性函数应用的前提条件是两个数互质,故不妨先将 A A A拆解为素数乘积形式:
A = ∏ i = 1 k p i r i A=\prod_{i=1}^k p_i^{r_i} A=i=1kpiri
其中 k k k A A A素数分解后的项数, p i p_i pi为素数, r i r_i ri p i p_i pi出现的次数。
例如: 20 = 2 2 ⋅ 5 1 20=2^2\cdot 5^1 20=2251
那么对于 N = A B N=A^B N=AB,就有:
N = A B = ∏ i = 1 k p i r i B N=A^B=\prod_{i=1}^k p_i^{r_iB} N=AB=i=1kpiriB
由于 B B B是对 A A A的整体次幂,故直接落于每个质因子上。由于乘积的每一项都是素数的次幂,故每一项对于其他项都是互质的,可以使用积性函数的特性,有:
[ D ( d ) ] ( N ) = [ D ( d ) ] ( A B ) = [ D ( d ) ] ( ∏ i = 1 k p i r i B ) = ∏ i = 1 k [ D ( d ) ] ( p i r i B ) = ∏ i = 1 k ∑ ( d ( p i r i B ) ) 3 [D(d)](N)=[D(d)](A^B)\\ =[D(d)]\left( \prod_{i=1}^k p_i^{r_iB}\right)\\ =\prod_{i=1}^k[D(d)]\left(p_i^{r_iB}\right)\\ =\prod_{i=1}^k\sum \left(d\left(p_i^{r_iB}\right)\right)^3 [D(d)](N)=[D(d)](AB)=[D(d)](i=1kpiriB)=i=1k[D(d)](piriB)=i=1k(d(piriB))3
每一个等号都是一次变换,我把过程尽量细化了,还看不太懂的话可以往上面翻一翻。
还记得 [ D ( d ) ] [D(d)] [D(d)]的定义吗?先求变量的各个因子,再求每一个因子的因子的个数。
由于 p i r i B p_i^{r_iB} piriB是素数次幂的形式,故其因子序列为 p i 0 , p i 1 , … , p i r i B , p_i^0,p_i^1,\dots ,p_i^{r_iB}, pi0,pi1,,piriB, r i B + 1 r_iB+1 riB+1项。
而每一项作为素数 p i p_i pi k k k次幂,其因子个数必然为 k + 1 k+1 k+1项,即 d ( p i k ) = k + 1 d\left( p_i^k\right)=k+1 d(pik)=k+1,故最终结果:
[ D ( d ) ] ( N ) = ∏ i = 1 k ( ∑ j = 1 r i B + 1 j 3 ) [D(d)](N)=\prod_{i=1}^k\left( \sum_{j=1}^{r_iB+1}j^3\right) [D(d)](N)=i=1k(j=1riB+1j3)
又由于简单的立方和公式,故有:
[ D ( d ) ] ( N ) = ∏ i = 1 k ( ( r i B + 1 ) × ( r i B + 1 + 1 ) 2 ) 2 [D(d)](N)=\prod_{i=1}^k\left( \frac{\left(r_iB+1\right)\times\left(r_iB+1+1\right)}{2}\right)^2 [D(d)](N)=i=1k(2(riB+1)×(riB+1+1))2
故,只需要求出 A A A的素数分解,得到每一个素数因子出现的次数 r i r_i ri,就可以解出来这道题目了!
我求素数分解的方式是线性素数筛,时间复杂度 O ( n ) O(n) O(n),具体原理可以百度。

java代码

/** 
* @Author weizhiwei
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;



public class Main {
	static int mod = 10007;
	public static void main(String[] args) throws IOException{
		InputReader in = new InputReader(System.in);
		ArrayList<Integer> prime = Prime.solve(1000000);
		int ts = 1;
		while(in.hasNext()) {
			long A = in.nextInt();
			long B = in.nextInt();
			ArrayList<Integer> r = new ArrayList<>();
			for(int i = 0; i < prime.size() && A>1; i++) {
				int pr = prime.get(i);
				if(A%pr==0) {
					int cnt = 0;
					while(A%pr==0) {
						A/=pr;
						cnt++;
					}
					r.add(cnt);//即文字叙述中的ri,每一个素数项的指数
				}
			}
			long ans = 1;
			for(int ri:r) {
				long n = ri*B+1;
				long tmp = (n*(n+1))/2 % mod;//立方和的一部分
				tmp *= tmp;//立方和
				tmp %= mod;
				ans *= tmp;
				ans %= mod;//每一项立方和的结果相乘
			}
			System.out.println("Case "+ts+": "+ans);
			ts++;
		}
	}
	//快速读入
	static class InputReader{
		StringTokenizer token;
		BufferedReader bf;
		InputReader(InputStream in){
			token = null;
			bf = new BufferedReader(new InputStreamReader(in));
		}
		String next(){
			try{
				while(token==null || !token.hasMoreTokens()){
					token = new StringTokenizer(bf.readLine());
				}	
			}catch(Exception e){}
			return token.nextToken();
		}
		int nextInt(){
			return Integer.parseInt(next());
		}
		boolean hasNext()  
		{
		     boolean result = false;
		     try {
		         result = bf.ready();
		     }catch (IOException e){
		     }
		     return result;
		}
	}
	static class Prime {
		/**
		 * 
		 * @param n 范围为[1.n]
		 * @return [1,n]之间的所有素数
		 */
		public static ArrayList<Integer> solve(int n) {
			ArrayList<Integer> ans = new ArrayList<>();
			int[] isPrime = new int[n+10];
			for(int i = 2; i <= n; i++) {
				if(isPrime[i]==0) {
					ans.add(i);
				}
				for(int p:ans) {
					if(i*p>n)
						break;
					isPrime[i*p] = 1;//筛去
					if(i%p==0)
						break;
				}
			}
			return ans;
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值