MY课题--费马小定理入门--ZOJ3785--Sabrina--Sabrinadol

0.写在前面

因为费马小定理的使用需要满足两个数是否互质(数论中大部分定理都需要,so,我接下来讲的worth积累)

先补充筛法

1.求素数用到的方法
(1)普通枚举 枚举到sqrt(n)就好
(2)朴素筛法
通过对每个数有无非平凡因子来判断
朴素筛法 nlogn ,这个时间复杂度的计算有些复杂
如下
n/2+n/3+n/4+…+n/n;
n(1/2+1/3+1/4+…+1/n)
后面那一坨大致就约等于 ln(n) (学过数竞应该知道)

int a[maxn],b[maxn],n;
int cnt=0;
//筛出 2 到 n 中的所有素数 


void naive_sieve(int n){
	for(int i=2;i<=n;i++)
	{
		if(!a[i]) b[cnt++]=i;
		for(int j=2*i;j<=n;j+=i)//从i+i往后筛所有的倍数
		a[j]=1;
	}
}

(3)埃式筛法
通过素因子来筛

int a[maxn],b[maxn],n;
int cnt=0;
//优化, nloglogn ,这里的计算跟上个差不多,埃式筛法 
void naive_sieve(int n){
	for(int i=2;i<=n;i++)
	{
		if(!a[i]) 
		{
			b[cnt++]=i;
			for(int j=2*i;j<=n;j+=i)//将此循环体拿到if依据里面
			//意思就是,在遍历筛的时候遇到的如果是合数就不用筛了,优化
			a[j]=1;
		} 
	}
}

(4)线性筛(欧拉筛)


void oula_sieve(int n)
{
	int cnt=0;
	for(int i=2;i<=n;i++)
	{
		if(!a[i]) b[cnt++]=a[i];
		for(int j=0;b[j]*i<=n;j++)
		{
			a[b[j]*i]=1;
//			保证b[j]是i*b[j]1的最小素因子 
			if(i%b[j]==0) break;
		}
	}
} 

大家可能对以上三种方法及其优化思路还有疑问,下面加深讲解
1.基本思想其实都是先筛掉有非平凡因数的合数筛掉,再进行存储
2.举下面 一个栗子
比如说我们要筛 12这个数
(1)朴素筛 : 除1外每个数都要去把12筛一遍
也就是我们扫到这些数都要去把12筛 : 2 3 4 6
(2)埃氏筛 : 除1外每个质因数都要去把12筛一遍
也就是我们扫到这些数都要去把12筛 : 2 3

(3)欧拉筛 :
可能有人不太懂
1–j代表的是下标
2–b[]存储找到的素数
代码中的第二重(if依据巧妙避开求重)可以让标记只让当前找到的素因数往后标记
3–还是举12的例子
12的最小质因数会将12筛出
也就是只有:2

4–总结欧拉筛:

每次用已筛出来的质数去筛更大的数,
每个合数只被它最小的质因子筛掉,
试想,如果26筛了12之后还没break,
而是用3
6筛掉18,那么18还会被29筛一次,就重复了
而根本原因就是6有2这个因子,
而3
6筛掉的数一定也有2这个因子,
3*6这个数应该被2这个因子筛掉,而不是3

然后是gcd

gcd(a,b)指的是a,的最大公约数
如果a,b互质那么 gcd(a,b)=1;
一般来讲我们求gcd是通过辗转相除法的
就是 gcd(a,b)=gcd(a,b%a);满足a>b
这里直接套一个递归就好了

int gcd(int a,int b)
{
    return b == 0 ? a : gcd(b,a % b);
}
//这个玩意可以这么读:b == 0否?b == 0的话返回a,b != 0的话返回gcd(b,a%b)
//就是辗转相除,除到0了那么上一个除数就是最大公约数
int gcd(int a,int b)
{
	if(b==0)
	return a;
	return (b,a%b);
}

1.内容

当gcd(a,p)=1时
a^(p-1)=1(mod p)
a的p-1次方取p的模为1

2.举例

如果现在我们要去求 2^100(mod 13)=?
很明显该数过大,不过我们首先可以考虑用二分的思想,一层一层取模运算。
但是,Sabrina提出了问题:有没有更好的办法呢?
肯定是有的
从费马小定理出发,我们是否可以将这个一百化为 n*(p-1)+k,n直接用100/12向下取整就好了,
这样的话,我们就直接考虑 2^4(mod 13)=?
Sabria听到后很开森,不过她仍然意犹未尽,于是有了下面这道例题

3.例题

传送门
今天星期六,S.和L.一起出去游玩,突然S.提出一个问题1^1 + 2^2 + 3^3 + … + N^N天后的哪一天?
L.一下子就解答了,你能吗?
输入
有多个测试用例。 第一行输入包含一个整数T,表示测试用例的数量。 对于每个测试用例:

只有一行包含一个整数N(1 <= N <= 1000000000)。

产量
对于每个测试用例,输出一个表示星期几的字符串。

样本输入
2
1
2
样本输出
Sunday
Thursday
暗示
一周包括周日,周一,周二,周三,周四,周五和周六。
Jīntiān xīngqíliù,11 + 22 + 33 +… + NN tiānhòu de nǎ yītiān?

Shūrù
yǒu duō gè cèshì yònglì. Dì yīxíng shūrù bāohán yīgè zhěngshù T, biǎoshì cèshì yònglì de shùliàng. Duìyú měi gè cèshì yònglì:

Zhǐyǒu yī xíng bāohán yīgè zhěngshù N(1 <= N <= 1000000000).

Chǎnliàng
duìyú měi gè cèshì yònglì, shūchū yīgè biǎoshì xīngqí jǐ de zìfú chuàn.

Yàngběn shūrù
2
1
2
yàngběn shūchū
xīngqírì
xīngqísì
ànshì
yīzhōu bāokuò zhōu rì, zhōuyī, zhōu’èr, zhōusān, zhōu sì, zhōu wǔ hé zhōu liù.

题解

Sabrina看到这道题有点感觉有点难了
但是一旁的同学笑了笑,这是一道非常水的题,用上费马小定理秒杀哦!

我们知道n^n%7= (n%7)^ n%7,令n%7=m,就相当于n-7*[n/7]
则原式=(m^ m%7)(m^ (n-m)%7)%7
举个例子,9 ^9%7=2 ^9%7=((2 ^2%7)
(2 ^7%7)) %7,
所以只要让(2 ^7%7)这个部分等于1,
而且这一部分,2的幂肯定是7的倍数,那么循环节就出现了,循环节的开端为
m ^m%7(m<7)。
我们知道(2 ^a%7) ^b%7=x ^ab%7,让该公式为1,且ab为7的倍数,则a等于6(费马小定理),得ab的最小值为42,也就是要重复就经过了42种情况
,所以n^n%7的循环节为42
294=42*7,即为11 + 22 + 33 + … + NN %7的循环节

但是Sabrina还是有一点疑惑,于是有了下面几张图

这个题中我们的p也就是一周的天数7,最开始的形式:


1^1     2^2     3^3     4^4     5^5     6^6     7^7
8^8     9^9     10^10   11^11   12^12   13^13   14^14
15^15   16^16   17^17   18^18   19^19   20^20   21^21
22^22   23^23   24^24   25^25   26^26   27^27   28^28
29^29   30^30   31^31   32^32   33^33   34^34   35^35
36^36   37^37   38^38   39^39   40^40   41^41   42^42
43^43   44^44   45^45   46^46   47^47   48^48   49^49

这里就相当于n-7*[n/7]的过程

在这里插入图片描good述

费马小定理转化后–>>(分别取6的模,然后来减掉)
1^1 2^2 3^3 4^4 5^5 6^0 0^1
1^2 2^3 3^4 4^5 5^0 6^1 0^2
1^3 2^4 3^5 4^0 5^1 6^2 0^3
1^4 2^5 3^0 4^1 5^2 6^3 0^4
1^5 2^0 3^1 4^2 5^3 6^4 0^5
1^0 2^1 3^2 4^3 5^4 6^5 0^0
1^1 2^2 3^3 4^4 5^5 6^0 0^1
最后一行重复,循环节长度为4

Sabrinadol懂了,你懂了吗

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值