彗星OJ - コンテスト#10 C.魚、大きなスプラッシュ

ポータル

問題の意味:
検索が最小\(X \) 満たす\(\ {X FRACは、(X + 1)} {2} \ = 0 N-%、N末端のLeq 12 \ 10 ^である{} \)
データの複数のセット、\(T \のLeq 100 \)

アイデア:

  • 剰余演算を考えることは、直接何二の残りの部分が、より複雑に関係しているようです。
  • より特別な最終結果があるということであるノート\(0 \)は、次に我々は、変換問題割り切れを検討します。
  • これは、式と等価である|(\ FRAC {X N \ \(X + 1)} {2}) 、すなわち\(2N | X(+ X. 1)\)
  • 注目\(N- \)範囲を、我々はでき\((O \ SQRT {N })\) 列挙する\(P、Q \)を、満足\(PQ = 2N \)
  • そして、そこに\(PQ | X-(X- + 1)\) 設定したいことがあり(= X-QBは、X-1はPA \ = +)\、そこ\(PA-QB = 1 \) 今同等知っています\(P、Q \) 解決するための最小の正の溶液\(B \)よう\(X \)が最小化されます。
  • 明らかに、これは拡張ユークリッドの古典的な問題があります。

このタイトルカードは、多くの場合、私たちは素因数に列挙を列挙しますので、最後の品質の因数分解は、最初の素数が出てふるい必要があるときのノートを取る、またはT.なります
最後に、拡張ユークリッドノートは、我々は正または負の長期治療を選択することができ解を得る、私は直接の回答による負長期治療を選びました。
(一つは関係なくの、第二の負の長期治療であるにかかわらず、最初の処理によって処理されている。これは、しばらくの間、もつれは何の関係もない、それは時間とアイテムの位置に対応するようにされています。)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 35, MAX = 1e6 + 5;

int T;
ll n;

bool chk[MAX];
int prime[MAX], tot;

void pre() {
    for(int i = 2; i < MAX; i++) {
        if(!chk[i]) {
            chk[i] = 1;
            prime[++tot] = i;
            for(ll j = 1ll * i * i; j < MAX; j += i) {
                chk[j] = 1;
            }
        }
    }
}

void exgcd(ll a, ll b, ll &x, ll &y) {
    if(b == 0) {
        x = 1, y = 0;
        return ;
    }
    exgcd(b,a%b,x,y);
    ll z = x ;
    x = y;
    y = z - y * (a / b);
}

int cnt;
ll tmp[N];

ll calc(ll a, ll b) {
    ll x, y;
    exgcd(a, b, x, y);
    y = (y % a + a) % a;
    if(y * b >= 0) y -= a;
    return -y * b;//按负项处理
}

ll dfs(int num, ll a, ll b) {
    if(num > cnt) return calc(a, b);
    return min(dfs(num + 1, a * tmp[num], b), dfs(num + 1, a, b * tmp[num]));
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    pre();
    cin >> T;
    while(T--) {
        cin >> n;
        n <<= 1;
        cnt = 0;
        for(int i = 1; i <= tot; i++) {
            if(prime[i] > n) break;
            if(n % prime[i] == 0) {
                tmp[++cnt] = 1;
                ll now = prime[i];
                while(n % prime[i] == 0) {
                    tmp[cnt] *= now;
                    n /= prime[i];
                }
            }
        }
        if(n > 1) tmp[++cnt] = n;
        ll ans = dfs(1, 1, 1);
        cout << ans << '\n';
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/heyuhhh/p/11502960.html