题目:http://codeforces.com/contest/1011/problem/E
题意:
有n种纸币,每种可以出任意多张,问k进制下余数有多少种,从小到大输出
分析:
由裴蜀定理得:
若x1*a1+x2*a2+…+xn*an=m,则gcd(a1,a2…an)|m
所以余数为gcd的整数倍
考虑可能xi为负数,但只需将xi+=k*inf,余数不变,而xi变成符合题意的正数
最后找循环节就跳出循环即可
时间复杂度O(n*log[max(ai)]+k)
代码:
#include <bits/stdc++.h>
using namespace std;
const int tmax=1e5+5;
int n,k,a[tmax],ans;
bool f[tmax];
int main()
{
cin>>n>>k;
int i,tmp=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]%=k;
a[1]=__gcd(a[1],a[i]);
}
while(1)
{
tmp=(tmp+a[1])%k;
if(f[tmp]==true) break;
f[tmp]=true;
}
for(i=0;i<k;i++)
if(f[i]==true) ans++;
printf("%d\n",ans);
for(i=0;i<k;i++)
if(f[i]==true) printf("%d ",i);
return 0;
}
总结裴蜀定理:
若gcd(a,b)=d;
1. 则对于任意整数x,y,有ax+by一定是d的倍数
2. 一定存在整数x,y,使得ax+by=d成立
3. a,b互质(d==1)的充要条件是存在整数x,y使得ax+by=1
4. ax+by=m有解的条件时d|m
推广:对于n个整数,若gcd(a1,a2,…,an)=d;
1. 存在x1,x2…,xn,使得x1*a1+x2*a2+…+xn*an=d
2. a1…an互质(d==1)的充要条件是存在x1…xn使得x1*a1+…xn*an=1
3. x1*a1+…xn*an=m有解的条件是d|m