欧拉函数+快速幂+快速乘(最幸运的数)

https://blog.csdn.net/lizhiwei2017/article/details/81543342

Chinese people think of '8' as the lucky digit. Bob also likes digit '8'. Moreover, Bob has his own lucky number L. Now he wants to construct his luckiest number which is the minimum among all positive integers that are a multiple of L and consist of only digit '8'.

Input

The input consists of multiple test cases. Each test case contains exactly one line containing L(1 ≤ L ≤ 2,000,000,000).

The last test case is followed by a line containing a zero.

Output

For each test case, print a line containing the test case number( beginning with 1) followed by a integer which is the length of Bob's luckiest number. If Bob can't construct his luckiest number, print a zero.

Sample Input

8
11
16
0

Sample Output

Case 1: 1
Case 2: 2
Case 3: 0

注意到凡是那种11111..... 22222..... 33333.....之类的序列都可用这个式子来表示:k*(10^x-1)/9
进而简化:8 * (10^x-1)/9=L * k (k是一个整数)
8*(10^x-1)=9L*k
d=gcd(9L,8)=gcd(8,L)
8*(10^x-1)/d=9L/d*k
令p=8/d q=9L/d p*(10^x-1)=q*k
因为p,q互质,所以q|(10^x-1),即10^x-1=0(mod q),也就是10^x=1(mod 9*L/d)
由欧拉定理可知,当q与10互质的时候,10^(φ(q))=1 (mod q),即必定存在一个解x。
而题目中要求的是最小的解,设为min,那么有a^min=1%q,因为要满足a^φ(q)=1%q,那么a^φ(q)肯定能变换成(a^min)^i。
所以接下来只要枚举φ(q)的因子,找出符合条件的最小者即可。

无解的时候就是q与10不互质的时候,因为若q与10有公因子d:
1.若d=2,q=2*k,那么10^x=2^x*5^x=1%2k
   即2^x*5^x=1+2k*m,左边为偶数,右边为奇数,显然矛盾。
2.若d=5,q=5*k,那么10^x=2^x*5^x=1%5k
   即2^x*5^x=1+5k*m,左边是5的倍数,右边不是5的倍数,显然矛盾。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
#define N 1000000

ll dp[N];
ll gcd(ll a, ll b) {
	return b ? gcd(b,a%b): a;
}
//求欧拉函数
ll eular(ll n) {
	ll m = n;
	for (ll i = 2; i*i <= n; i++) {
		if (n%i == 0) {
			m -= m / i;
			while (n%i == 0) {
				n /= i;
			}
		}
	}
	if (n > 1)
		m -= m / n;
	return m;
}
//快速乘
ll multi(ll a, ll b, ll mod) {
	a%=mod;
	b%=mod;
	ll res = 0;
	while (b) {
		if (b & 1) {
			res = (res + a) % mod;
		}
		a = (a * 2) % mod;
		b >>= 1;
	}
	return res;
}
//快速幂结合快速乘
ll quick_pow(ll a, ll b, ll mod) {
	ll res = 1;
	while (b) {
		if (b & 1) {
			res = multi(res, a, mod);
		}
		a = multi(a, a, mod);
		b >>= 1;
	}
	return res;
}

int main() {
	ll l,cnt=1;
	while (~scanf("%lld", &l) && l) {
		memset(dp, 0, sizeof(dp));
		ll m = 9 * l / gcd(8, l);
		//欧拉定理成立条件
		if (gcd(10, m) != 1) {
			cout << "Case " << cnt++ << ": " << 0<< endl;
			continue;
		}
		ll ans = eular(m);
		ll t = 0;
		//记录欧拉函数的因子
		for (ll i = 1; i*i <= ans; i++) {
			if (ans%i == 0) {
				dp[t++] = i;
				if (ans != i * i)
					dp[t++] = ans / i;
			}
		}
		sort(dp, dp + t);//因子从小到大排
		ll book;
		//枚举欧拉函数的因子直到10^dp[i]=1(mod m);
		for (ll i = 0; i < t; i++) {
			if (quick_pow(10, dp[i], m) == 1) {
				book = i;
				break;
			}
		}
		cout << "Case " << cnt++ << ": " << dp[book] << endl;
	}

	return 0;
}

 

### 回答1: RSA-CRT 算法是用于加速 RSA 密钥的模幂运算的一种方法。这种方法通过使用 Chinese Remainder Theorem(中国剩余定理)来减少计算量,从而提高效率。 下面是 RSA-CRT 算法的 Python 代码实现: ``` def rsa_crt(m: int, d: int, p: int, q: int, dp: int, dq: int) -> int: qinv = pow(q, p - 2, p) m1 = pow(m, dp, p) m2 = pow(m, dq, q) h = (qinv * (m1 - m2)) % p return m2 + h * q ``` 在这段代码中,`m` 是要解密的信息,`d` 是 RSA 私钥,`p` 和 `q` 是 RSA 密钥的两个质因,`dp` 和 `dq` 是 RSA 私钥的两个 CRT 参快速幂算法是一种用于快速计算幂的算法,它通过递归的方式来实现。递归的关键在于,对于一个的幂,如果幂是奇,则可以用其平方的一半再乘上它本身来得到结果;如果幂是偶,则可以直接将幂的一半平方来得到结果。 Robin-Miller 算法是一种用于快速计算模的算法。它的基本思想是,对于一个的模运算,如果模是奇,则可以将其分解成两个较小的奇之和,然后对这两个分别进行模运算,再将结果相加得 ### 回答2: RSA-CRT算法是一种加密算法,其中使用了两个较慢的算法:快速幂算法和Robin-Miller算法。下面是关于这两种算法的精简的Python代码实现。 1. 快速幂算法: ```python # 计算快速幂 def fast_power(base, exponent, modulus): result = 1 base = base % modulus while exponent > 0: if exponent % 2 == 1: result = (result * base) % modulus exponent = exponent // 2 base = (base * base) % modulus return result ``` 2. Robin-Miller算法: ```python # Robin-Miller素性测试 def is_prime(n, k): # 排除小于2的和偶 if n < 2 or n % 2 == 0: return False # 定义辅助函 def cal_s_d(n): d = n - 1 s = 0 while d % 2 == 0: d /= 2 s += 1 return s, d # 进行k次测试 for _ in range(k): a = random.randint(2, n - 1) s, d = cal_s_d(n - 1) x = fast_power(a, d, n) if x == 1 or x == n - 1: continue for _ in range(s - 1): x = (x * x) % n if x == 1: return False if x == n - 1: break else: return False return True ``` 希望以上代码能对您有所帮助,如有任何问题,请随时告诉我。 ### 回答3: RSA-CRT算法中使用了快速幂算法和Robin-Miller算法来提高计算效率。下面是一个使用Python编写的简化代码: # 快速幂算法函 def fast_power(base, exponent, modulus): result = 1 while exponent > 0: if exponent % 2 == 1: result = (result * base) % modulus base = (base * base) % modulus exponent = exponent // 2 return result # Robin-Miller算法函 def robin_miller(n): # 根据Robin-Miller算法找到一个与n互质的a a = 2 while True: if gcd(a, n) == 1: break a += 1 # 使用Robin-Miller算法进行快速判断n是否为素 x = fast_power(a, n-1, n) if x != 1: return False else: return True # 主程序 def main(): p = 61 # 选择素p q = 53 # 选择素q n = p * q # 计算n euler_n = (p - 1) * (q - 1) # 计算n的欧拉函数值 # 使用Robin-Miller算法判断n是否为素 if robin_miller(n) == False: print("n不是素") return # 选择一个与euler_n互质的e e = 17 # 计算e的模反元素d d = 0 while (e * d) % euler_n != 1: d += 1 # 加密 plaintext = 123 # 待加密的明文 ciphertext = fast_power(plaintext, e, n) # 加密后的密文 # 解密 decryptedtext = fast_power(ciphertext, d, n) # 解密后的明文 print("解密后的明文为:", decryptedtext) main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值