【扩展欧几里得 && 数学】Codeforces Round #499 (Div. 2) E. Border

本文探讨了在给定n种不同面值钱币且每种面值钱币数量无限的情况下,如何找出所有可能的求和结果对k取模后的不同余数值。通过扩展欧几里得算法,证明了存在一组正整数使得(ax+by)%k=gcd(a,b,k)。最后提供了一段C++代码实现,该程序能高效地输出所有不同的余数值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Step1 Problem

有 n 种面值的钱,每种面值的钱有无数张。
你可以选择任意张钱,求和 % k,输出所有不一样的结果。
数据范围:
1 <= n <= 1e5, 2 <= k <= 1e5. 1 <= 面值大小 <= 1e9.
例:
input:
2 8
12 20
output:
2
0 4

Step2 Ideas:

就是求:
(x*a[1] + y*a[2] + … + z*a[n] )%k 对于任意 x, y, … ,z 输出的所有不一样的结果
扩展欧几里得:一定存在整数 x, y 满足ax + by = gcd(a, b)
所以一定存在正整数 x, y:(ax+by)%k = gcd(a, b, k)
简单证明一下:一定存在正整数 x, y 满足 (ax+by)%k = gcd(a, b),如果 x, y 是负数 只要加 k 的倍数即可,因为 %k 左边的式子不改变。

Step3 Code:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n, k;
    while(~scanf("%d %d", &n, &k))
    {
        int ans = k, num;
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &num);
            ans = __gcd(ans, num);
        }
        printf("%d\n", k/ans);
        for(int i = 0; i < k; i += ans)
        {
            if(i == 0)
            printf("%d", i);
            else printf(" %d", i);
        }
        printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值