zoukankan      html  css  js  c++  java
  • Comet OJ

    考试的时候推出来了,但是忘了 $exgcd$ 咋求,成功爆蛋~

    这里给出一个求最小正整数解的模板:

    ll solve(ll A,ll B,ll C) 
    {    
        ll x,y,g,b,ans; 
        gcd = exgcd(A,B,x,y);                 
        if(C%gcd!=0) return -1;        
        x*=C/gcd,B/=gcd; 
        if(B<0) B=-B;   
        ans=x%B;      
        if(ans<=0) ans+=B;  
        return ans;        
    } 
    

    大概就是这样. 

    说一下题:

    可以将题目转化成求 $frac{ans(ans+1)}{2}mod n=0$ 的最小 $ans$.
    将式子转化一下,即 $ans(ans+1)=2n imes y$,其中 $y$ 是个整数.
    易得 $ans$ 与 $ans+1$ 是互质的,所以 $2n$ 中每一种不同的质因子只能贡献给 $ans,ans+1$ 中的一个.
    而 $10^{12}$ 以内的数字最多只会有不到十多个本质不同的质因子,所以可以枚举子集.
    考虑枚举出 $A$ 和 $B$,令 $A imes x=ans,B imes y=ans+1$.
    则需要满足 $Ax-By=-1,gcd(x,y)=1$
    但其实我们发现 $gcd(x,y)=1$ 是不用判的,因位如果等式成立,则 $gcd(x,y)$ 就一定是 $1$.
    那么,我们只需找到 $Ax-By=-1$ 的最小 $x$ 正整数解就行了.
    这个可以用 $exgcd$ 直接求,但是有一些细节需要注意:

    1. $A,B$ 都需要大于 $0$.
    2. 我们想求 $x$,所以 $y$ 到底是多少我们是不关心的,直接无视掉就好.

    Code: 

    #include <cstdio>  
    #include <vector> 
    #include <algorithm>   
    #define N 1000006 
    #define inf 100000000000000000
    #define ll long long 
    #define LL long long
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std; 
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(b==0)
        {
            x=1,y=0;
            return a;
        }
        ll ans=exgcd(b,a%b,x,y);
        ll tmp=x;
        x=y,y=tmp-a/b*y;
        return ans;
    }         
    vector<ll>v;   
    int tot; 
    int prime[N],is[N];    
    void init() 
    { 
        int i,j; 
        for(i=2;i<N;++i) 
        {
            if(!is[i]) prime[++tot]=i;         
            for(j=1;j<=tot&&1ll*prime[j]*i<1ll*N;++j) 
            {
                is[prime[j]*i]=1; 
                if(i%prime[j]==0) break;    
            }
        }    
    }
    ll solve(ll A,ll B) 
    {    
        ll x,y,g,b,ans; 
        g = exgcd(A,B,x,y);                 
        if(-1%g) return inf;        
        x*=-1/g,y*=g;    
        B/=g; 
        if(B<0) B=-B;   
        ans=x%B;      
        if(ans<=0) ans+=B;  
        return ans*A; 
    } 
    int main() 
    { 
        // setIO("input");  
        init(); 
        int T,i,j; 
        scanf("%d",&T); 
        while(T--)
        {
            ll n,h,answer=inf; 
            scanf("%lld",&n),h=n;
            for(i=1;i<=tot;++i) 
            {
                if(h%prime[i]==0) 
                { 
                    ll kk=1;    
                    while(h%prime[i]==0) 
                    { 
                        h/=prime[i];   
                        kk*=prime[i];    
                    }      
                    v.push_back(kk);    
                }       
            }
            if(h) v.push_back(h);                  
            int len=v.size();    
            for(i=0;i<(1<<len);++i) // 枚举所有子集 
            {  
                ll tmp=1; 
                for(j=0;(1<<j)<=i;++j) 
                {  
                    if(i&(1<<j)) 
                        tmp*=v[j];         
                }
                ll A=tmp,B=2*n/tmp;     
                answer=min(answer,min(solve(A,B),solve(B,A)));  
            }
            printf("%lld
    ",answer); 
            v.clear();    
        }
        return 0; 
    }
    

      

  • 相关阅读:
    JS时间框架之舍弃Moment.js拥抱Day.js
    快速理解Token,Cookie,Session
    一篇文章彻底弄懂CAS实现SSO单点登录原理
    debugging books
    debugging tools
    X64相关文章
    AMD developer
    kernel debugging
    Windows Kernel Security Training Courses
    windbg commands
  • 原文地址:https://www.cnblogs.com/guangheli/p/11481512.html
Copyright © 2011-2022 走看看