3696 The Luckiest number 最小X整数倍数 大整数质因数分解及欧拉函数,dfs求大整数的所有约数

The Luckiest number
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 2349 Accepted: 537

Description

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
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#define bignum long long
using namespace std;
//求a,b的最大公约数
bignum gcd(bignum a,bignum b)
{
    return b==0?a:gcd(b,a%b);
}
//求a*b%c,因为a,b很大,所以要先将b写成二进制数,再加:例如3*7=3*(1+2+4);
bignum mulmod(bignum a,bignum b,bignum c)
{
    bignum cnt=0,temp=a;
    while(b)
    {
        if(b&1) cnt=(cnt+temp)%c;
        temp=(temp+temp)%c;
        b>>=1;
    }
    return cnt;
}
//求a^b%c,再次将b写成二进制形式,例如:3^7=3^1*3^2*3^4;
bignum powmod(bignum a,bignum b,bignum c)
{
    bignum cnt=1,temp=a;
    while(b)
    {
        if(b&1) cnt=mulmod(cnt,temp,c);//cnt=(cnt*temp)%c;
        temp=mulmod(temp,temp,c);//temp=(temp*temp)%c;
        b>>=1;
    }
    return cnt;
}
//Miller-Rabin测试n是否为素数,1表示为素数,0表示非素数
int pri[10]={2,3,5,7,11,13,17,19,23,29};
bool Miller_Rabin(bignum n)
{
    if(n<2) return 0;
    if(n==2) return 1;
    if(!(n&1)) return 0;
    bignum k=0,m;
    m=n-1;
    while(m%2==0) m>>=1,k++;//n-1=m*2^k
    for(int i=0;i<10;i++)
    {
        if(pri[i]>=n) return 1;
        bignum a=powmod(pri[i],m,n);
        if(a==1) continue;
        int j;
        for(j=0;j<k;j++)
        {
            if(a==n-1) break;
            a=mulmod(a,a,n);
        }
        if(j<k) continue;
        return 0;
    }
    return 1;
}
//pollard_rho 大整数分解,给出n的一个非1因子,返回n是为一次没有找到
bignum pollard_rho(bignum C,bignum N)
{
    bignum I, X, Y, K, D;
    I = 1;
    X = rand() % N;
    Y = X;
    K = 2;
    do
    {
        I++;
        D = gcd(N + Y - X, N);
        if (D > 1 && D < N) return D;
        if (I == K) Y = X, K *= 2;
        X = (mulmod(X, X, N) + N - C) % N;
    }while (Y != X);
    return N;
}
//找出N的最小质因数
bignum rho(bignum N)
{
    if (Miller_Rabin(N)) return N;
    do
    {
        bignum T = pollard_rho(rand() % (N - 1) + 1, N);
        if (T < N)
        {
              bignum A, B;
              A = rho(T);
              B = rho(N / T);
              return A < B ? A : B;
        }
    }
    while(1);
}
//N分解质因数,这里是所有质因数,有重复的
bignum AllFac[1100];
int Facnum;
void findrepeatfac(bignum n)
{
    if(Miller_Rabin(n))
    {
        AllFac[++Facnum]=n;
        return ;
    }
    bignum factor;
    do
    {
        factor=pollard_rho(rand() % (n - 1) + 1, n);
    }while(factor>=n);
    findrepeatfac(factor);
    findrepeatfac(n/factor);
}
//求N的所有质因数,是除去重复的
bignum Fac[1100];
int num[1100];
int len;//0-len
void FindFac(bignum n)
{
    len=0;
    //初始化
    memset(AllFac,0,sizeof(AllFac));
    memset(num,0,sizeof(num));
    Facnum=0;
    findrepeatfac(n);
    sort(AllFac+1,AllFac+1+Facnum);
    Fac[0]=AllFac[1];
    num[0]=1;
    for(int i=2;i<=Facnum;i++)
    {
        if(Fac[len]!=AllFac[i])
        {
            Fac[++len]=AllFac[i];//important
        }
        num[len]++;
    }
}
//求n的欧拉函数值
bignum oula(bignum n)
{
    FindFac(n);
    bignum cnt=n;
    for(int i=0;i<=len;i++)
    {
        cnt-=cnt/Fac[i];
    }
    return cnt;
}
//枚举n的所有因子  cnt
/*bignum Fac[1100];
int num[1100];
int len;//0-len
*/
bignum yinzi[100000];
bignum yinzinum;//初始化在main中(0-yinzinum-1)
void dfs(int id,bignum cnt)
{
    yinzi[yinzinum++]=cnt;
    if(id==len+1)
    {
        return ;
    }
    bignum temp=1;
    for(int i=0;i<=num[id];i++)
    {
        dfs(id+1,cnt*temp);
        temp*=Fac[id];
    }
}
int main()
{
    srand(time(NULL));
    bignum l;
    int pl=1;
    while(cin>>l&&l)
    {
        bignum m=9*l/gcd(9*l,8);
        //cout<<"m="<<m<<endl;
        if(gcd(10,m)>1)
        {
            cout<<"Case "<<pl++<<": 0"<<endl;
            continue;
        }
        if(powmod(10,1,m)==1)
        {
            cout<<"Case "<<pl++<<": 1"<<endl;
            continue;
        }
        bignum n=oula(m);
        //cout<<"n="<<n<<endl;
        FindFac(n);
        //枚举n的所有因子
        yinzinum=0;//因子个数
        dfs(0,1);
        sort(yinzi,yinzi+yinzinum);
        yinzinum=unique(yinzi,yinzi+yinzinum)-yinzi;
        //......................
        for(int i=0;i<yinzinum;i++)
        {
            if(powmod(10,yinzi[i],m)==1)
            {
                cout<<"Case "<<pl++<<": "<<yinzi[i]<<endl;
                break;
            }
        }
    }
    return 0;
}
好的,我可以为您解答这个问题。首先,为了模拟微信发红包的两种发放方式,我们需要了解两种发放方式的具体实现方式。 第一种方式是“平均分配法”,即将红包金额平均分配给每个领取人。这种方式的优点是简单、公平,但缺点是可能会导致某些人领取到的金额较少,无法满足个性化需。 第二种方式是“随机分配法”,即将红包金额随机分配给每个领取人。这种方式的优点是个性化、趣味性强,但缺点是可能会导致某些人领取到的金额较多,不够公平。 下面是两种方式的具体实现代码: 平均分配法: ```python import random def send_hongbao_1(num, money): avg_money = money / num # 平均每个人分配的金额 money_list = [avg_money for i in range(num)] # 初始化每个人的金额 return money_list ``` 随机分配法: ```python import random def send_hongbao_2(num, money): money_list = [] for i in range(num-1): # 生成一个随机数,表示当前领取人的金额比例 rate = random.uniform(0, 1) money_i = round(money * rate, 2) # 四舍五入保留两位小数 money_list.append(money_i) money -= money_i money_list.append(money) # 最后一个领取人获得剩余的金额 random.shuffle(money_list) # 打乱顺序,增加趣味性 return money_list ``` 以上两个函数分别表示了两种发放方式,其中`num`表示领取红包人数,`money`表示发放金额。这两个函数返回一个列表,表示每个领取人获得的金额。 为了显示红包发放情况,并打印红包运气王的名单,我们可以在两个函数中加入一些输出语句: ```python def send_hongbao_1(num, money): avg_money = money / num money_list = [avg_money for i in range(num)] print("红包发放情况:") for i in range(num): print("第{}个人获得了{}元".format(i+1, money_list[i])) max_money = max(money_list) luckiest = [i+1 for i, j in enumerate(money_list) if j == max_money] print("红包运气王是:", luckiest) return money_list def send_hongbao_2(num, money): money_list = [] for i in range(num-1): rate = random.uniform(0, 1) money_i = round(money * rate, 2) money_list.append(money_i) money -= money_i money_list.append(money) random.shuffle(money_list) print("红包发放情况:") for i in range(num): print("第{}个人获得了{}元".format(i+1, money_list[i])) max_money = max(money_list) luckiest = [i+1 for i, j in enumerate(money_list) if j == max_money] print("红包运气王是:", luckiest) return money_list ``` 上述代码中,`max_money`表示领取金额最多的人获得的金额数,`luckiest`表示获得最多金额的人的编号列表。 最后,如果您想从`.xlsx`表格中抽取人物,可以使用`pandas`库中的`read_excel`函数读取表格,并使用`sample`函数随机抽取人物。示例代码如下: ```python import pandas as pd df = pd.read_excel('人物表.xlsx') people_list = df['姓名'].tolist() # 获取所有人物的姓名列表 selected_list = random.sample(people_list, num) # 随机抽取num个人物 ``` 以上代码中,`num`表示需要抽取的人数。`people_list`表示所有人物的姓名列表,`selected_list`表示随机抽取的人物姓名列表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值