[牛客]Wannafly挑战赛22 A.计数器 ---- 裴蜀定理+扩展欧几里得

版权声明:本文为博主原创文章,转载请预先通知博主(〃'▽'〃)。 https://blog.csdn.net/m0_37624640/article/details/82667065

题目任意门

做法:

  • 裴蜀定理:若a,b是整数,且(a,b)=d,那么对于任意的整数x,y,ax+by=k中的k一定是d的倍数。
  • 现在我们知道n个数,a1,a2,a3,……,an。我们把他们通过gcd联系起来
  • 设gcd(a1,a2,a3,……,an) = p
  • 那么一定存在一组解k1,k2,……,kn 使得 a1*k1+a2*k2+……+an*kn = k*P (k为任意整数)     即裴蜀定理
  • 那么我们想求得其实就是(k*p)%m,通过找规律发现这个式子是存在循环节的。
  • 举个栗子:
  • a1 = 12,a2 = 3, gcd(a1,a2) = 3    另m = 12
  • (a1)% m = 0
  • (a1+a2)%m = 3
  • (a1+2*a2)%m = 6
  • (a1+3*a2)%m = 9
  • (a1+4*a2)%m = 0
  • (a1+5*a2)%m = 3
  • ……………………
  • 所以我们只要求出循环节的头和尾就知道有几个mod (m) 不同值的个数了
  • 我们发现0也是gcd(a,b)的倍数,所以直接使得(k*p)%m = 0   转换一下 变成 k*p-m*k1 = 0
  • 我们令a = p,  b = m ,   x = k,   y = -k1  ,即转换成了ax+by = 0
  • 由扩展欧几里得可知存在一个通解公式x = x0+b/(gcd(a,b)) *t  =  x0 + m/(gcd(p,m)) *t
  • 我们再x0 = 0,那么循环节的个数就是m/(gcd(p,m))  即mod(m) 不值的个数

AC代码:

#include<bits/stdc++.h>
#define IO          ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb(x)       push_back(x)
#define sz(x)       (int)(x).size()
#define sc(x)       scanf("%d",&x)
#define pr(x)       printf("%d\n",x)
#define abs(x)      ((x)<0?-(x):x)
#define all(x)      x.begin(),x.end()
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const double PI = 4*atan(1.0);
const int maxm = 1e8+5;
const int maxn = 1e4+5;
const int INF = 0x3f3f3f3f;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int a[105];
int main()
{
    #ifdef LOCAL_FILE
    freopen("in.txt","r",stdin);
    #endif // LOCAL
    IO;
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>a[i];
    int ans = gcd(a[0],a[1]);
    for(int i=2;i<n;i++) ans = gcd(ans,a[i]);
    cout<<m/gcd(ans,m)<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37624640/article/details/82667065
今日推荐