【集训】简单数论

简单数论

P8255 [NOI Online 2022 入门组] 数学游戏

xz,则一定无解。

x=d×ay=d×b,其中 gcd(a,b)=1。那么有 gcd(x,y)=d。则 z=x×y×gcd(x,y)=d3×a×b

我们知道 xz,那么可以求出 zx=d2×b。由于 gcd(a,b)=1,所以 gcd(zx,x2)=gcd(d2×b,d2×a2)=d2。若 gcd(zx,x2) 不是完全平方数,则无解。

gcd(zx,x2) 开方即可得到 d。那么:zxgcd(zx,x2)=d2×bd=d×b=y所以我们有:y=zxgcd(zx,x2)

时间复杂度 O(Tlogx)

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}
#define rd rd()

void wt(int x){
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        wt(x / 10);
    putchar(x % 10 + '0');
    return;
}
void wt(char x){
    putchar(x);
}
void wt(int x, char k){
    wt(x),putchar(k);
}

namespace Star_F{
    ll x, t;
    void Main(){
        cin >> x >> t;
        if (t % x != 0) {
            cout << -1 << endl;
            return;
        }
        t /= x;
        ll g = __gcd(x * x, t), s = sqrt(g) + 0.5;
        if (s * s != g) {
            cout << -1 << endl;
            return;
        }
        cout << t / s << endl;
    }
}

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ClockA;
    int T=1;
    T=rd;
    while(T--) Star_F::Main();
    // ClockB;
    return 0;
}


/*
*          ▀▀▀██████▄▄▄       _______________
*          ▄▄▄▄▄  █████████▄  /                 \
*         ▀▀▀▀█████▌ ▀▐▄ ▀▐█ | Code has no BUG!  |
*      ▀▀█████▄▄ ▀██████▄██ | _________________/
*       ▀▄▄▄▄▄  ▀▀█▄▀█════█▀ |/
*            ▀▀▀▄  ▀▀███ ▀       ▄▄
*         ▄███▀▀██▄████████▄ ▄▀▀▀▀▀▀█▌   ______________________________
*       ██▀▄▄▄██▀▄███▀ ▀▀████      ▄██  █                               \\
*    ▄▀▀▀▄██▄▀▀▌████▒▒▒▒▒▒███     ▌▄▄▀▀▀▀█_____________________________ //
*    ▌    ▐▀████▐███▒▒▒▒▒▐██▌
*    ▀▄▄▄▄▀   ▀▀████▒▒▒▒▄██▀
*              ▀▀█████████▀
*            ▄▄██▀██████▀█
*          ▄██▀     ▀▀▀  █
*         ▄█             ▐▌
*     ▄▄▄▄█▌              ▀█▄▄▄▄▀▀▄
*    ▌     ▐                ▀▀▄▄▄▀
*     ▀▀▄▄▀     ██
* \  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
* \- ▌           Name: Star_F              ▀ ▀
*  - ▌                            (o)          ▀
* /- ▌            Go Go Go !               ▀ ▀
* /  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
*/

P1082 [NOIP 2012 提高组] 同余方程

exgcd 模板题

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int exgcd(int a, int b, int &x, int &y){
    if (!b){
        x = 1, y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
int main(){
    int a, b;
    cin >> a >> b;
    int x, y;
    exgcd(a, b, x, y);
    cout << (x % b + (LL)b) % b << endl; 
    return 0;
}

P1390 公约数的和

假设先求这个ans=k=1nkfk

  • fk 表示 gcd(i,j)=k 的个数

  • gk 表士 k|gcd(i,j) 的个数,显然 gk=fk+f2k++fmk

gk=nk2 (i,jnk)

所以 f[k]=nk2(f2k+f3k+)

复杂度是 n×(1+12+13+...+1n)

所以总复杂的为 O(nH(n))H(n) 为调和级数

因为 n 不大,这个算法常数小,所以就比算 d=1nϕ(d)nd2 要快一些

而本题就等于:

ansi=1ngcd(i,i)2=ansn×(n+1)22

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}
#define rd rd()

void wt(int x){
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        wt(x / 10);
    putchar(x % 10 + '0');
    return;
}
void wt(char x){
    putchar(x);
}
void wt(int x, char k){
    wt(x),putchar(k);
}

namespace Star_F{
    ll n,ans,f[2000010];
    void Main(){
        cin >> n;
        for (int i = n; i; --i){
            f[i] = n / i * (n / i);
            for (int j = i << 1; j <= n; j += i)
                f[i] -= f[j];
            ans += f[i] * i;
        }
        cout << (ans - n * (n + 1) / 2 >> 1) << endl;
    }
}

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ClockA;
    int T=1;
    // T=rd;
    while(T--) Star_F::Main();
    // ClockB;
    return 0;
}


/*
*          ▀▀▀██████▄▄▄       _______________
*          ▄▄▄▄▄  █████████▄  /                 \
*         ▀▀▀▀█████▌ ▀▐▄ ▀▐█ | Code has no BUG!  |
*      ▀▀█████▄▄ ▀██████▄██ | _________________/
*       ▀▄▄▄▄▄  ▀▀█▄▀█════█▀ |/
*            ▀▀▀▄  ▀▀███ ▀       ▄▄
*         ▄███▀▀██▄████████▄ ▄▀▀▀▀▀▀█▌   ______________________________
*       ██▀▄▄▄██▀▄███▀ ▀▀████      ▄██  █                               \\
*    ▄▀▀▀▄██▄▀▀▌████▒▒▒▒▒▒███     ▌▄▄▀▀▀▀█_____________________________ //
*    ▌    ▐▀████▐███▒▒▒▒▒▐██▌
*    ▀▄▄▄▄▀   ▀▀████▒▒▒▒▄██▀
*              ▀▀█████████▀
*            ▄▄██▀██████▀█
*          ▄██▀     ▀▀▀  █
*         ▄█             ▐▌
*     ▄▄▄▄█▌              ▀█▄▄▄▄▀▀▄
*    ▌     ▐                ▀▀▄▄▄▀
*     ▀▀▄▄▀     ██
* \  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
* \- ▌           Name: Star_F              ▀ ▀
*  - ▌                            (o)          ▀
* /- ▌            Go Go Go !               ▀ ▀
* /  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
*/

P1516 青蛙的约会

求:x+kmy+kn(modl) ,其中 k 为所求。

化简:

x+km(y+kn)=lz,zZxy+k(mn)lz=0k(mn)lz=(xy)

我们设 S=xy,W=nm,这个式子便可写作:kW+lz=S,于是用 exgcd 求出答案

让我们回到原问题。

因为 kj=kmin+lgcd(W,l)×t,所以 kmin=kjmodlgcd(W,l) 这是因为 exgcd 的性质

而因为这个 k 是建立在 exgcd 得出的方程上的,方程右边是 gcd(W,l) 而不是 S。所以最后我们需要将结果 ×Sgcd(W,l)

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

LL exgcd(LL a, LL b, LL &x, LL &y)
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }

    LL d = exgcd(b, a % b, y, x);
    y -= a / b * x;

    return d;
}

int main()
{
    LL a, b, m, n, L;
    cin >> a >> b >> m >> n >> L;

    LL x, y;
    LL d = exgcd(m - n, L, x, y);
    if ((b - a) % d) puts("Impossible");
    else
    {
        x *= (b - a) / d;
        LL t = abs(L / d);
        cout << (x % t + t) % t << endl;
    }

    return 0;
}

P4777 【模板】扩展中国剩余定理(EXCRT)

设有一组两两互质的正整数 m1,m2,,mn(即 gcd(mi,mj)=1 对任意 ij),以及一组整数 a1,a2,,an。中国剩余定理指出,下面的同余方程组在模 M=m1×m2××mn 下有唯一解:

{xa1(modm1)xa2(modm2)xan(modmn)

  1. 解的存在性与唯一性
  • 存在性:存在解 x 满足所有同余方程。
  • 唯一性:解在模 M 下唯一,即所有解可表示为 x+kMkZ)。
  1. 解为x=i=1naiMitimodM

证明:

  • 因为 Mi=M/mi,是除 mi 之外所有模数的倍数,所以 ki,aiMiti0(modmk)
  • 又因为 Miti1(modmi) ,所以 aiMitiai(modmi)
  • 综上所述,将公式带入原方程组即能够满足所有的同余式。
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 10;
int n;
int A[N], B[N];
LL exgcd(LL a, LL b, LL &x, LL &y)  // 扩展欧几里得算法, 求x, y,使得ax + by = gcd(a, b)
{
    if (!b)
    {
        x = 1; y = 0;
        return a;
    }
    LL d = exgcd(b, a % b, y, x);
    y -= (a / b) * x;
    return d;
}
int main(){
    scanf("%d", &n);
    LL M = 1;
    for (int i = 0; i < n; i ++ ){
        scanf("%d%d", &A[i], &B[i]);
        M *= A[i];
    }
    LL res = 0;
    for (int i = 0; i < n; i ++ ){
        LL Mi = M / A[i];
        LL ti, x;
        exgcd(Mi, A[i], ti, x);
        res = (res + (__int128)B[i] * Mi * ti) % M;
        // B[i] * Mi * ti可能会超出long long范围,所以需要转化成__int128
    }
    cout << (res % M + M) % M << endl;
    return 0;
}
posted @   Star_F  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示