彗星OJ - exgcd +派生コンテスト#10魚ビッグスプラッシュ

試験時間の打ち上げが、$のexgcdの$がたに忘れてしまったが、成功爆発卵を求めて〜

ここではテンプレートが最小の正の整数解であります:

LL(LLのA、LLのB、LLのC)解く
{     
    LLのX、Y、G、Bを、ANS。
    GCD = exgcd(A、B、X、Y)。                 
    もし(!C%GCD = 0)リターン-1;        
    X * = C / GCD、B / = GCD。
    (B <0)B = -B場合;   
    ANS = X%のB;      
    (ANS <= 0)ANS + = Bであれば、  
    ANSを返します。        
}

それはおそらくケースです。 

タイトルについての講演:

質問が$ \ FRAC {ANS(ANS +シークに変換することができる MOD N = 0 $ \ {2} 1)} 最小の$ ANSの$。
それを変換式、即ち$ ANS(ANS + 1)= 2N \回Yの$、$は、の整数であるY $
ANS $ $、容易に入手可能であり、$ ANS + 1 $ 1 $、異なる素因数が$ ANSに寄与することができる$ $各ので2N互いに素である、ANS + 。
そしてダース異なる素因数性質未満以内$ 10 ^ {12} $だけ数値までは、サブセットを挙げることができる。
$ $ $とB $を列挙検討順序を$ \倍のx =アンス、Bの\ Y =アンスは、+ 1 $。回
、それが満たす必要$ AX-ことで= -1、GCD (X、Y)= 1 $
が、実際に、我々は$のGCD(x、y)を見つけ= 1 $ 等式が成立する場合の位置は、その後、$ GCDので、。(x、y)は$は必ずしも$ 1 $で、宣告されていない
ので、私達はちょうどライン上= -1 $ $ X $最小の正の整数解ではAX-$を見つける必要があります。の
これは$ exgcd $即時要件することができますが、注意が必要ないくつかの詳細があります。

  1. $ A、B $ $を超える$ 0にする必要があります。
  2. 私たちは、$ xに$を見つけたい、最後に$ yを$はそんなに私たちは、直接無視アウトだけで結構気にしないです。

コード: 

#include <cstdioを>   
する#include <ベクトル> 
の#include <アルゴリズム>    
の#define N 1000006 
の#define INF 100000000000000000 
の#defineは長い長いっ
の#define LL長い長
の#define setIO(S)freopenは(S ".IN"、 "R" 、STDIN)
名前空間stdを使用。
(-1,11,11-のB、LL&X、LL&Y)exgcd LL 
{ 
    (B == 0)場合
    、{ 
        X = 1、Y = 0 
        返します。
    } 
    LL ANS = exgcd(B、%のB、X、Y)。
    LLのTMP = X。
    X = Y、Yは、TMP-A / Bの* yを=。
    ANSを返します。
}          
ベクトル<LL> V。   
int型のTOT; 
INTプライム[N]、[N]です。    
INITを無効()
{  
    私は、jはint型。
    (I = 2の場合、iがNを<。 
    { 
        もしプライム[++ TOT = I(ある[I]!)。         
        ため(J = 1; J <= TOT && 1LL *プライム[J] * I <1LL * N; ++ j)は
        { 
            ある[プライム[J] * I] = 1。
            もし(I%、プライム[J] == 0)ブレーク。    
        } 
    }     
} 
(LLのA、LLのB)解決ちゃう
{     
    LLのX、Y、G、B、ANS。
    G = exgcd(A、B、X、Y)。                 
    IF(-1%G)戻りINF。        
    X * = - 1 / G、Y * = G。    
    B / = G。
    (B <0)B = -B場合;   
    ANS = X%のB;      
    (ANS <= 0)ANS + = Bであれば、  
    ANS *のAを返します。
} 
int型のmain()
{ 
    // setIO( "入力")。  
    その中に();
    int型T、I、J。
    scanf関数( "%のD"、&T)。
    (T--)一方
    { 
        LL N、H、答え= INF。
        scanf関数( "%のLLD"、&n)は、H = N。
        用(i = 1; I <= TOT; ++ I)
        { 
            IF(H%のプライム[I] == 0)
            { 
                LLのKK = 1。    
                一方、(時間%プライム[I] == 0)
                { 
                    H / =プライム[I]。   
                    KK * =プライム[i]は、    
                }       
                v.push_back(KK)。    
            }        
        } 
        IF(H)v.push_back(H)。                  
        INT LEN = v.size()。    
        (I = 0; I <(1 << LEN)。
        {   
            LL TMP = 1。
            用(J = 0、(1 << J)<= I; ++ j)は
            {  
                IF(I&(1 << J))
                    TMP * = V [J]。         
            } 
            LL A = TMP、B = 2 * N / TMP。     
            答え=分(答え、分((B、A)を解く、(A、B)を解きます))。  
        } 
        のprintf( "%LLDする\ n"、答え)。
        v.clear();    
    } 
    0を返します。
}

  

おすすめ

転載: www.cnblogs.com/guangheli/p/11481512.html