链接:https://www.nowcoder.com/acm/contest/160/A
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
有一个计数器,计数器的初始值为0,每次操作你可以把计数器的值加上a1,a2,...,an中的任意一个整数,操作次数不限(可以为0次),问计数器的值对m取模后有几种可能。
输入描述:
第一行两个整数n,m
接下来一行n个整数表示a1,a2,...,an
1≤n≤100
1≤m,a1,a2,...,an≤1000000000
输出描述:
输出一个整数表示答案
示例1
输入
复制
3 6
6 4 8
输出
复制
3
思路:
裴蜀定理:
- 对于任何整数a,b且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别的,一定存在整数x,y使得ax+by=d成立。
重要推论:
- a,b互质的充要条件是存在整数x,y使得ax+by=1。
假设对数an取的个数为kn,可得到如下等式:
a1*k1+a2*k2+a3*k3+......an*kn=p
设g=gcd(a1,a2,a3...an)
当p为g的倍数时,等式有解。
注意:这里求公约数的是时候要把m也算进去。
g=gcd(a1,a2...an) 设g*x%m=a,(a是模m后的值,不同的a的个数就是答案)
则有 gx-my=a,裴蜀定理,若想要等式有解a必须为gcd(g,m)的倍数。又因为a是模m后的值,则答案是:m/gcd(g,m)(在m内能有几个a成立)
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
#define ll long long
ll gcd(ll a,ll b){
if(a<b)swap(a,b);
if(b==0)return a;
return gcd(b,a%b);
}
int main(){
ll n,m;
scanf("%lld%lld",&n,&m);
ll tmp=m,a;
for(int i=0;i<n;i++){
scanf("%lld",&a);
tmp=gcd(tmp,a);
}
printf("%lld\n",m/tmp);
}