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;
}