欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数论——同余和费马小定理

程序员文章站 2022-06-08 11:06:27
...

同余:如果对于a和b,有a-b求余m等于零,则我们说a和b同余,记为a≡b(mod m)

其实我们也可以通俗易懂的总结一下,就是a mod m == b mod m

互质:gcd(a,b) == 1,我们就说两个数是互质的

费马小定理:对于a和p两个互质的数,存在等式a^(p-1)≡1(mod p)

我们举个经典的例子吧

对于2^100 mod 13 我可以看到,这里13和2是互质的,我们要用费马小定理的话应该怎么办?

是不是要构造出13-1啊!所以有 2^100≡(2^((12*8)+4))(mod 13),到了这一步,我们就可以用费马小定理了

对于2^12 是不是有2^12≡1mod13,所以我们去替换就行了

说的更明白点就是,2^100 和 2^((12*8)+4)) 取摸 13 的值相等,也就是和 (2^(12*8)mod13 * 2^4mod13)mod13相等,也就是和((1mod13)^8*2^4mod13)mod13相等,说到这里,大家就应该明白了吧,我这辈子应该也忘不了了吧

下面给一个经典题目吧

这个题目重在条件转换,这是数论题目的常规操作

我们首先需要理解S(k) be the number of (x1,x2,......,xk),这句话的意思是S(k)代表k个数能相加等于N的序列数目

然后还有一个问题是,例如N等于3,k = 2时,1+2和2+1是不是一个序列,这个问题模棱两可,但是数论问题就是要找规律,我们认定这是两个序列的话,容易得出来,S(1) + .... +S(N)等于2^(n-1),这样就可以用到费马小定理了!

具体见下面的AC代码 

数论——同余和费马小定理

Input

2

Output

2
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
typedef long long ll;
string n;
int main()
{
    while(cin>>n)
    {
        ll mod = 1000000006;
        ll sum = 0;
        ll power = 10;
        ll k = n.size()-1;
        while(n[k] == '0')
        {
            k--;
        }
        n[k] = n[k] - 1;
        for(ll i = n.size()-1; i > k; i--)
        {
            n[i] = '9';
        }
        for(ll i = 0; i < n.size(); i++)
        {
            sum = sum * power + (n[i]-'0');
            if(sum >= mod)
            {
                sum %= mod;
            }
        }
        ll a = 2;
        ll result = 1;
        ll mod1 = 1000000007;
        while(sum)
        {
            if(sum % 2 == 1) result = (result*a)%mod1;
            a = (a*a)%mod1;
            sum/=2;
        }
        cout<<result<<endl;
    }
    return 0;
}

 

 

相关标签: 数论