The Luckiest number--欧拉函数+快速幂

题目:大致意思就是给你一个L,1<=L<=2,000,000,000,让你找出一个最小的数字,该数字是L的倍数,并且只由数字8组成,输出该数字的位数。

分析:这个数字可以表示成8 * (10 ^ x - 1)/9,目的就是求出最小的x,满足L | 8 * (10 ^ x - 1)/9,' | '表示整除。

设d = gcd(8 , L),下面是我的理解:

在L | 8 * (10 ^ x - 1)/9两边同时除d,就会得到L / d | 8 / d * (10 ^ x - 1)/9,令a=L / d,b=8 / d,原式就变成a | b * (10 ^ x - 1)/9,a和b必然是互质的,所以右边整除左边与b没有关系,b可以去掉。那么,L / d | 8 / d * (10 ^ x - 1)/9 ⇔ L / d | (10 ^ x - 1)/9 

⇔ 9L / d | 10 ^ x - 1 ⇔ 10 ^ x ≡ 1( mod  9L / d )。

有一个结论:

若正整数 a , n 互质,则满足 a ^ x ≡ 1 (mod n) 的最小正整数 x0 是 φ(n) 的约数。

那我们只需要求出φ(9L / d)的所有因子,找到最小的满足条件的就可以了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
ll n,m,ans[100010];//ans存m的因子 
ll gcd(ll a,ll b)
{
	return b?gcd(b,a%b):a;
}
ll euler(ll num)//欧拉函数 
{
	ll ans=num;
	for(int i=2;i<=sqrt(num);i++)
	{
		if(num%i==0)
		{
			ans=ans/i*(i-1);
			while(num%i==0)
				num/=i;
		}
	}
	if(num>1) ans=ans/num*(num-1);
	return ans;
}
ll ksc(ll a,ll b,ll mod)//快速乘 
{
	ll ans=0;
	while(b)
	{
		if(b&1)
			ans=(ans+a)%mod;
		b>>=1;
		a=(a+a)%mod;
	}
	return ans;
}
ll check(ll a,ll b,ll mod)//快速幂,检查是否满足条件 
{
	ll ans=1;
	while(b)
	{
		if(b&1)
			ans=ksc(ans,a,mod);
		b>>=1;
		a=ksc(a,a,mod);
	}
	return ans;
}
int main()
{
	int cas=1;
	while(~scanf("%lld",&n),n)
	{
		int cnt=0,flag=0;
		ll d=gcd(8,n);
		m=euler(9*n/d);//phi[9*n/d]
		for(int i=1;i<=sqrt(m);i++)//找出m的所有因子 
		{
			if(m%i==0)
			{
				ans[++cnt]=i;
				ans[++cnt]=m/i;
			}
		}
		sort(ans+1,ans+cnt+1);//排序,从小的开始找 
		for(int i=1;i<=cnt;i++)
		{
			if(check(10,ans[i],9*n/d)==1)
			{
				flag=1;
				printf("Case %d: %lld\n",cas++,ans[i]);
				break;
			}
		}
		if(!flag) printf("Case %d: 0\n",cas++);
	}
	return 0;
}

 

好的,这是一个比较有趣的问题!首先,我们需要明确两种发放方式。第一种是平均分配法,即将红包金额平均分配给领取红包的每个人。第二种是随机分配法,即将红包金额随机分配给领取红包的每个人。下面是两种发放方式的实现,并且能够读取文件里面的人物。 ```python import random # 定义一个函数,用于读取文件里面的人物 def read_file(filename): with open(filename, 'r') as f: lines = f.readlines() return [line.strip() for line in lines] # 平均分配法 def average_red_packet(num_people, total_amount): amount = total_amount / num_people result = [amount] * num_people return result # 随机分配法 def random_red_packet(num_people, total_amount): result = [] remain_amount = total_amount remain_people = num_people for i in range(num_people): if remain_people == 1: result.append(remain_amount) else: amount = random.randint(1, remain_amount - remain_people + 1) result.append(amount) remain_amount -= amount remain_people -= 1 return result # 测试代码 if __name__ == '__main__': filename = 'people.txt' people = read_file(filename) num_people = len(people) total_amount = 100 # 发放的红包总金额 print('红包总金额:', total_amount) print('领取红包的人数:', num_people) print() # 平均分配法 print('平均分配法:') red_packets = average_red_packet(num_people, total_amount) for i in range(num_people): print('{}领取了{}元'.format(people[i], red_packets[i])) print() # 随机分配法 print('随机分配法:') red_packets = random_red_packet(num_people, total_amount) for i in range(num_people): print('{}领取了{}元'.format(people[i], red_packets[i])) print() # 找到红包运气王 max_amount = max(red_packets) luckiest = [] for i in range(num_people): if red_packets[i] == max_amount: luckiest.append(people[i]) print('红包运气王:', ','.join(luckiest)) ``` 需要注意的是,我们在读取文件里面的人物时,使用了`strip()`函数来去除每行末尾的换行符。这是因为在文件中,每行末尾都有一个换行符。如果不去除的话,会影响后面对人物的处理。另外,需要确保人物的数量不小于领取红包的人数,否则程序会出现错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值