nowCoder 计数器
有一个计数器,计数器的初始值为0,每次操作你可以把计数器的值加上a1,a2,...,ana_1,a_2,...,a_na1,a2,...,an中的任意一个整数,操作次数不限(可以为0次),问计数器的值对m取模后有几种可能。
输入描述:
第一行两个整数n,mn,mn,m
接下来一行n个整数表示a1,a2,...,ana_1,a_2,...,a_na1,a2,...,an
1≤n≤1001≤n≤1001≤n≤100
1≤m,a1,a2,...,an≤10000000001≤m,a_1,a_2,...,a_n≤10000000001≤m,a1,a2,...,an≤1000000000
输出描述:
输出一个整数表示答案
示例1
输入
3 6
6 4 8
输出
3
AC代码
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n, m, g, a;
cin >> n >> m;
g = m;
for(int i = 1; i <= n; i++){
cin >> a;
g = __gcd(a, g);
}
cout << m / g << endl;
return 0;
}
代码分析
1.裴蜀定理
若a,ba,ba,b是整数,且gcd(a,b)=dgcd(a, b)=dgcd(a,b)=d,那么对于任意整数x,y,ax+byx,y,ax+byx,y,ax+by都一定是ddd的倍数,特别地,一定存在整数x,yx,yx,y,使得ax+by=dax+by=dax+by=d成立
由上述定理描述可知:
a1x1+a2x2+...+anxn=P∗gcd(a1,a2,a3,...,an)(P为整数)a_1x_1+a_2x_2+...+a_nx_n=P*gcd(a_1,a_2,a_3,...,a_n)(P为整数)a1x1+a2x2+...+anxn=P∗gcd(a1,a2,a3,...,an)(P为整数)
由题意有
(a1x1+a2x2+a3x3+...+anxn)%m=r(a_1x_1+a_2x_2+a_3x_3+...+a_nx_n)\%m=r(a1x1+a2x2+a3x3+...+anxn)%m=r
将取模运算进行转化(kkk为商,rrr为余数):
(a1x1+a2x2+a3x3+...+anxn)=km+r(a_1x_1+a_2x_2+a_3x_3+...+a_nx_n)=km+r(a1x1+a2x2+a3x3+...+anxn)=km+r
r=a1x1+a2x2+a3x3+...+anxn−kmr=a_1x_1+a_2x_2+a_3x_3+...+a_nx_n-kmr=a1x1+a2x2+a3x3+...+anxn−km
由裴蜀定理有:
r=a1x1+a2x2+a3x3+...+anxn+(−k)m=P∗gcd(a1,a2,a3,...,an,m)r=a_1x_1+a_2x_2+a_3x_3+...+a_nx_n+(-k)m=P*gcd(a_1,a_2,a_3,...,a_n,m)r=a1x1+a2x2+a3x3+...+anxn+(−k)m=P∗gcd(a1,a2,a3,...,an,m)
假设gcd(a1,a2,a3,...,an,m)=Agcd(a_1,a_2,a_3,...,a_n,m)=Agcd(a1,a2,a3,...,an,m)=A则有r=P∗A(A为常数)r=P*A(A为常数)r=P∗A(A为常数)
因为PPP在本题中为正整数,则PPP可取0,1,2,...,Pmax0,1,2,...,P_{max}0,1,2,...,Pmax且每个取值对应一个rrr,故求出PmaxP_{max}Pmax即可知道对应的余数rrr可能个数
P=rgcd(a1,a2,a3,...,an,m)P=\frac r {gcd(a_1,a_2,a_3,...,a_n,m)}P=gcd(a1,a2,a3,...,an,m)r
因为rrr为余数,由余数必小于除数有r<mr<mr<m有
P=rgcd(a1,a2,a3,...,an,m)<mgcd(a1,a2,a3,...,an,m)P=\frac r {gcd(a_1,a_2,a_3,...,a_n,m)} < \frac m {gcd(a_1,a_2,a_3,...,a_n,m)}P=gcd(a1,a2,a3,...,an,m)r<gcd(a1,a2,a3,...,an,m)m
Pmax=mgcd(a1,a2,a3,...,an,m)P_{max}=\frac m {gcd(a_1,a_2,a_3,...,a_n,m)}Pmax=gcd(a1,a2,a3,...,an,m)m
该除式自动向下取整,故问题得解
2.最大公约数gcdgcdgcd
typedef ll long long;
ll gcd(ll a, ll b){
return b == 0 ? a : gcd(b, a % b);
}