数论——同余和费马小定理
程序员文章站
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;
}