HDU 1788 模余运算

题目   http://acm.hdu.edu.cn/showproblem.php?pid=1788

题意:中文..

解题思路:模余运算,模板题,目前自己不能直接拍出来,但是理解它绝对没问题...

#include<iostream>
#include<cmath>
using namespace std;
typedef __int64 int64;
int64 a[30],b[30],mod;

int64 gcd(int64 x,int64 y){
    if(y==0) return x;
    return gcd(y,x%y);
}

int64 Ext_eud(int64 a,int64 b,int64 &x,int64 &y){
    if(b==0) {
        x=1;y=0;
        return a;
    }
    int64 d=Ext_eud(b,a%b,x,y);
    int64 t=x;
    x=y;
    y=t-a/b*y;
    return d;
}

int64 inv(int64 a,int64 n){
    int64 x,y;
    int64 t=Ext_eud(a,n,x,y);
    if(t!=1) return -1;
    return ( x%n+n )%n;
}

bool merge( int64 a1,int64 n1,int64 a2,int64 n2,int64 &a3,int64 &n3 ){
    int64 d=gcd(n1,n2);
    int64 c=a2-a1;
    if(c%d)  return false;
    c=(c%n2+n2)%n2;
    c/=d;
    n1/=d;
    n2/=d;
    c*=inv(n1,n2);  /// 逆元
    c%=n2;
    c*=n1*d;
    c += a1;
    n3 = n1*n2*d;
    a3 = ( c%n3+n3 )%n3;
    return true;
}

int64 china_reminder(int64 len,int64*a,int64*n){
    int64 a1=a[0],n1=n[0];
    int64 a2,n2;
    for(int i=1;i<len;i++){
        int64 aa,nn;
        a2=a[i],n2=n[i];
        if(!merge(a1,n1,a2,n2,aa,nn)){
            return -1;
        }
        a1=aa;
        n1=nn;
    }
    mod=n1;
    return (a1%n1+n1)%n1;
}
int main(){
    int num,k;
    while(cin>>num>>k,num || k){
        int64 lcm=1;
        for(int i=0;i<num;i++){
            scanf("%I64d",&a[i]);  /// a[] 除数
            lcm = a[i]/gcd( lcm,a[i] )*lcm;
            b[i]=a[i]-k;    ///  b[]余数
        }
        int64 sum=china_reminder(num,b,a);
        while(sum<0)
            sum += lcm;
        printf("%I64d\n",sum);
    }
}

### HDU 443 约瑟夫问解析 #### 解思路 约瑟夫环问是经典的算法挑战之一,在处理此类问时,通常采用递推的方法来寻找规律。对于HDU 443而言,核心在于理解当人数减少一位后剩下的序列如何映射回原有序列中的位置[^1]。 每当移除一名参与者时,剩成员会形成一个新的更短的循环结构。假设当前总共有`n`名玩家参与游戏,并按照某种规则决定谁会被淘汰出局(比如每数到特定数字就被排除),那么最终存活者的索引可以通过构建一个函数`f(n)`表示出来。这个函数描述了在规为`n`的情况下最后一个幸存者的位置与较小规子问解决方案间的关系。 具体来说,设`f(n)`代表初始状态下有`n`个人时最后剩下那个人原本所在的位置,则可以建立如下递推公式: \[ f(n)=(f(n−1)+k)\% n \] 这里`k`指的是报数周期长度,即每隔多少位就有人被淘汰。而解过程就是不断地缩小圈子大小直至只剩一人为止[^2]。 #### 代码实现 下面给出Python版本的具体编码方式用于计算给定条件下谁能成为最后一人站立的人: ```python def josephus_problem(n, k): pos = 0 # 初始化第一个仅有的元素下标为0 for i in range(2, n + 1): # 循环迭代增加人数至目标数量 pos = (pos + k) % i # 更新新加入后的安全位置 return pos + 1 # 返回实际编号而非数组索引形式的结果 if __name__ == "__main__": N = int(input()) # 输入参加游戏的人数 K = int(input()) # 输入间隔数K result = josephus_problem(N, K) print(f"The survivor is at position {result}.") ``` 上述程序接收两个参数作为输入:一个是总的参赛人员数目`N`;另一个则是计数步长`K`。它利用简单的数学运算实现了高效的解答方案而不必逐一拟整个流程,从而能够应对较大的数据范围需[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值