《数论整理一》

前言:数论很难也很有意思,慢慢回顾和慢慢学,记录自己的感悟和理解。

keeping going !

欧拉函数:

假定phi(x)为x的欧拉函数,这个函数表示的就是1~i中和i互质的数。例phi(1) = 1,phi(2) = 1,phi(8) = 4。

欧拉函数的通式$phi(x) = x * \prod_{x = 1}^{tot} (1-\frac{1}{pi})$//tot为x的质因子的个数,注意是质因子。

那么我们对这个式子化简一下:$phi(x) = x * \prod_{x = 1}^{tot} (\frac{pi-1}{pi})$

那么就可以o(sqrt(n))得到一个数的欧拉函数。

代码思想:因为都是质因子,那么我们做质因子分解即可。

然后边分解边乘。

LL eular(LL x)
{
    LL ans = x;
    int m = sqrt(x);
    for(rg int i = 2;i <= m;++i)
    {
        if(x%i == 0)
        {
            ans = ans/i*(i-1);//注意先除后乘,防止爆精度
            while(x/i == 0) x /= i;
        }
    }
    if(x > 1) ans = ans/x*(x-1);
    return ans;
}
View Code

 欧拉函数求和通式:定义$s[i] = \sum_{j = 1}^{i} phi[j]$

可由杜教筛得 $s[i] = \frac{i*(i+1)}{2} - \sum_{j = 2}^{i} s[\frac{i}{j}]$

欧拉定理:

 当满足a与m互质时,有$a^{b} mod (m) \equiv a^{b mod phi[m]} mod (m)$

欧拉降幂:

由欧拉定理,我们可以得到欧拉降幂的公式。

显然用的条件是在次数过大时。次数小直接快速幂就可以了。

当$gcd(a,m) = 1  , a^{b} mod (m) \equiv a^{bmod(phi[m])} mod (m)$

当$gcd(a,m) != 1 , b >= phi[m] , a^{b} mod (m) \equiv a^{bmod(phi[m]) + phi[m]} mod (m)$

其他直接快速幂。

模板题:洛谷P5091 【模板】扩展欧拉定理

这里我们直接去判断b 是否 > 最大的模数就行。

LL eular(LL x)
{
    LL ans = x,m = sqrt(x);
    for(rg LL i = 2;i <= m;++i)
    {
        if(x%i == 0)
        {
            ans = ans/i*(i-1);
            while(x%i == 0) x /= i;
        }
    }
    if(x > 1) ans = ans/x*(x-1);
    return ans;
}
LL quick_mi(LL a,LL b,LL p)
{
    LL re = 1;
    while(b)
    {
        if(b&1) re = re*a%p;
        a = a*a%p;
        b >>= 1;
    }
    return re;
}
int main()
{
    LL a;a = read();
    LL m;m = read();
    string s;cin >> s;
    int len = s.size();
    LL ans;
    if(len <= 8)
    {
        LL ma = 0;
        for(rg int i = 0;i < len;++i) ma = ma*10+s[i]-'0';
        ans = quick_mi(a,ma,m);
    }
    else
    {
        LL phi = eular(m),ma = 0;
        if(__gcd(a,m) == 1)//底数和模数互质
        {
            for(rg int i = 0;i < len;++i) ma = (ma*10+s[i]-'0')%phi;
            ans = quick_mi(a,ma,m);
        }
        else
        {
            for(rg int i = 0;i < len;++i) ma = (ma*10+s[i]-'0')%phi;
            ans = quick_mi(a,ma+phi,m);
        }
    }
    printf("%lld\n",ans);
    system("pause");    
}
View Code

威尔逊定理:

当p为质数时有$(p-1)! \equiv -1 mod(p)$

也可得$(p-2)! \equiv 1 mod(p)$

即(p - 1)! mod p = p - 1 

这里的变形推导没推出来。太菜了~

 这里介绍下同余变换法则:

$a \equiv b mod (m)$表示a-b可以整除m,也就是可以推得下面的第二个

$a \equiv b mod (m) \rightarrow (a+b) \equiv 0 mod (m)$

$a \equiv b mod (m) \rightarrow (a-b) \equiv 0 mod (m)$

$a \equiv b mod (m) \rightarrow a * c \equiv b * c mod (m)$

$a \equiv b mod (m) \rightarrow a^{n} \equiv b^{n} mod (m)$

多个式子:如果a ≡ x(mod d),b ≡ m(mod d),则

a+b ≡ x+m (mod d)
a-b ≡ x-m (mod d)
a*b ≡ x*m (mod d )
其实和前面单个的变换一样,因为b和m对d取模后就是一样的数了
 
这题就是威尔逊定理的应用。
由令3k+6 = p-1.
那么求的式子就变成了$s[n] = \sum_{k = 1}^{n}[\frac{(p-1)!+1}{p} - \frac{(p-1)!}{p}]$
那么前面那个分数就是 $\frac{(p-1)!+1}{p}$
那么由威尔逊定理可得$(p-1)! \equiv -1 mod(p) \rightarrow (p-1)!+1 \equiv 0 mod(p)$
也就是表示当p为质数时,(p-1)!+1 整除 p。
那么(p-1)!不整除p。
那么由于[]操作,后面的那个数显然比前面的少1。因为1显然<p。所以不可能降过1.
此时答案就是[1] = 1。
当p不为质数时,(p-1)!+1 不整除 p.
因为威尔逊定理是一个充要条件:那么就有$\frac{(p-1)!+1}{p}$和$\frac{(p-1)!}{p}$的整数部分相同。
可以理解为因为(p-1)!+1 和 (p-1)!都不整除p,那么他们都是p的k倍。然后+1不凑成整数,无法增加1倍。
所以这里的答案就是[0] = 0
 提交莫名CE..
// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<string,int> pii;
const int N = 1e6+5;
const int M = 2e5+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;
void FRE(){/*freopen("data1.in","r",stdin);
freopen("data1.out","w",stdout);*/}

int f[N];
bool check(int x)
{
    if(x < 2) return false;
    int m = sqrt(x);
    for(rg int i = 2;i <= m;++i) if(x%i == 0) return false;
    return true;
}
void init()
{
    for(rg int i = 1;i < N;++i)
    {
        int x = 3*i+7;
        if(check(x)) f[i] = f[i-1]+1;
        else f[i] = f[i-1]+0;
    }
}
int main()
{
    init();
    int ca;ca = read();
    while(ca--)
    {
        int n;n = read();
        printf("%d\n",f[n]);
    }
    system("pause");    
}
View Code

 

posted @ 2020-09-08 22:16  levill  阅读(209)  评论(0编辑  收藏  举报