Loading

整除学习笔记

1.1整除

1.定义

\(a\)是非零整数,如果存在一个整数\(q\)使得\(b=a\times q\),那么就说\(b\)\(a\)整除,记做\(a|b\),称\(b\)\(a\)的倍数,\(a\)\(b\)的约数

整除具有一些性质

  1. 如果\(a|b\)\(b|c\)那么\(a|c\).令\(b=k_1\times a,c=k_2\times b\),那么有\(c=k_1\times k2\times a\),即\(a|c\)

  2. \(a|b且a|c\iff a|(b\times x+c\times y),(x,y\in Z)\)

  3. \(m\neq 0\),那么\(a|b\iff (m\times a)|(m\times b)\)

  4. 设整数\(x,y\)满足\(a\times x+b\times y=1\),且\(a|n,b|n\),那么\((a\times b)|n\)

    证明:

    \(\because a|n, b|n\)

    根据性质3得:\((a\times b)|(b\times n)\)\((a\times b)|(a\times n)\)

    又由性质2得:\((a\times b)|(a\times n\times x+b\times n\times y)\)

    其中\(a\times n\times x+b\times n\times y=n\times(ax+by)=n\times 1=n\)

    \(\therefore (a\times b)|n\)

  5. 如果\(b=q\times d+c\),那么\(d|b\)的必要条件为\(d|c\)

2.例题

1.1-1教堂

题意描述

ROMA城中有一些古典的印度式建筑,这些建筑和周围的欧洲建筑风格格格不入。这些伪装成教堂的建筑其实是某国特工的基地。Tomas接受了一项任务,就是从某个教堂出发,逐个访问这些教堂,搞清楚每一个教堂的内部结构,并回到出发的地方。这些教堂很有规律地构成了一个\(m\times n\)的矩形,每个教堂和它的八个方向的教堂有直接的路径相连。水平或垂直方向相邻的教堂之间的路程均为\(1\)。请问Tomas至少需要走多远的路,才能完成这个危险而艰巨的任务呢?

输入

输入一行两个整数m和n\((m,n\leq 10000)\)

输出

输出一行一个实数,表示最少需要走的路程,保留两位小数。

分析

用一些小数据可以得知答案与\(n,m\)的奇偶性有关

#include <bits/stdc++.h>
using namespace std;
int n, m;
int main()
{
    cin >> n >> m;
    if(n == 1 || m == 1)
        printf("%.2lf", (double)(m + n - 2) * 2);
    else
    {
        if(m * n % 2 == 1)
            printf("%.2lf", (double)(n * m - 1 + 1.414));
        else
            printf("%.2lf", (double)(n * m));
    }
    return 0;
}

imes k-n\times c=gcd()

1.1-2密码

题面

分析

首先,一个二元一次不定方程的一般形式为\(ax+by=c\).其中\(a,b,c\in Z并且a\times b\neq0\).这个方程有整数解的前提条件为\(gcd(a,b)|c\)

\(x_0,y_0\)为该方程的一组整数解,那么该方程的所有整数解可以表示为

\( \begin{cases} x=x_0+\frac{b}{gcd(a,b)}\times t\\ y=y_0+\frac{a}{gcd(a,b)}\times t \end{cases} \)

\(x\)为密码,观察这个式子:\(x\times k-n\times c=gcd(x,n)\)

可以得到:这个方程对于\(k,c\)是一定有正整数解的

所以:一定存在一个\(k\)使得\(x\times k\%=gcd(x,n)\)

由题意,\(x\)是密码,那么\((x+x)\%n=2x\%n\)也是密码,类似的\(3x\%n\)也是密码......

综上所述\(x\times k\%n=gcd(x,n)\),\(x\times k\%n\)也是密码

结论1:如果\(x\)是密码,\(gcd(x,n)\)为密码

\(x,y\)为两个密码,易得\((px+qy)\%n\)也是密码

\(ax+by=gcd(x,y)\)一定有解,所以

$ax+by\equiv gcd(x,y)\pmod n $一定有解

\(\because ax+by\equiv ax+by+pnx+qny \pmod n\)

\(\therefore (a+pn)x+(b+qn)y\equiv ax+by\pmod n,(p,q\in Z)\)

\(\therefore (a+pn)x+(b+qn)y\equiv gcd(x,y)\pmod n\)一定有解,并且\((a+pn),(b+qn)\geq 0\)

\(\because ((a+pn)x+(b+qn)y)\%n\)是密码

\(\therefore gcd(x,y)\)是密码

结论2:如果\(x,y\)是密码,那么\(gcd(x,y)\)为密码

对于任意的一个密码集合\(A\),分析

  1. \(A\)中所有数的\(gcd=x\)

  2. 由结论2得\(x\in A\)

  3. 如果密码集合中有比\(x\)小的数\(y\),则\(gcd(x,y) < x\),矛盾,所以\(x\)\(A\)中最小的数

所以\(A\)中所有的数为\(x,2x,3x,4x......\)

约束条件如下:

  1. \(A\)中数尽量多,\(x\)尽量小

  2. 由结论1得,集合中有两个书\(a_k,gcd(n,a_k)\),所以\(x|gcd(n,a_k)\)

  3. 对于\(\forall{1\leq i<k}\),\(x|a_i\)不能成立

实现

\(a_k=gcd(n,a_k)\),在\(O(\sqrt{n})\)时间内处理出\(a_k\)所有的因子,存在\(q\)数组中,接着去除所有为\(gcd(a_i,a_k)\)的因数,除去后的最小因子为\(x\),答案为\(n/x\)

Code

#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL n, k, a[550005], q[550005], f[550005], cnt, ans;
int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> k;
    for (int i = 1; i <= k; i++)
        cin >> a[i];
    a[k] = __gcd(a[k], n);
    for (int i = 1; i < k; i++)
        a[i] = __gcd(a[i], a[k]);
    for (LL i = 1; i * i <= a[k]; i++)
    {
        if (a[k] % i == 0)
        {
            q[++cnt] = i;
            if(i * i != a[k]) q[++cnt] = a[k] / i;
        }
    }
    sort(q + 1, q + 1 + cnt);
    for(int i = 1; i < k; i ++)
        f[lower_bound(q + 1, q + cnt + 1, a[i]) - q] = 1;
    for(int i = 1; i <= cnt; i ++)
        if(f[i])
            for(int j = 1; j < i; j ++)
                if(q[i] % q[j] == 0)
                    f[j] = 1;
    for(ans = 1; f[ans]; ans ++);
    cout << n / q[ans];
    return 0;
}
posted @ 2020-12-28 23:31  zhangwenxuan  阅读(229)  评论(0)    收藏  举报