2019 Multi-University Training Contest 3 - 1006 - Fansblog - 打表 - 暴力
Posted yinku
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019 Multi-University Training Contest 3 - 1006 - Fansblog - 打表 - 暴力相关的知识,希望对你有一定的参考价值。
http://acm.hdu.edu.cn/showproblem.php?pid=6608
题意:给一个比较大的质数P(1e14以内),求比它小的最大的质数Q(貌似保证存在的样子,反正我没判不存在),求Q!modP的值。
一开始觉得是个什么神仙题,但是怎么全场都绿了一片,瞬时感觉智商受到了侮辱。想了很多什么奇奇怪怪的性质,都不太清楚,然后队友卡1007的时候我打了个对P找ans的表看了一下。发现当P-Q=2的时候就是ans=1???
然后打个(P-2)!%P的表,发现小数据都这样过,估计也是真的这样子。
那么考虑怎么找这个Q,首先肯定特判掉P=3,然后Q必然是奇数。
考虑暴力找Q的复杂度:首先根据质数定理(或者直接打1e7表出来知道)得到质数的数量大概6e5这样子,验证Q是质数一圈暴力。
假如Q不是质数,极端情况,是两个不同质数的积,那么这样的数的分布应该是很大的。
根据下面的代码可以打出这样的极端合数:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e7;
int pri[MAXN + 5], pritop;
bool notpri[MAXN + 5];
//pritop从1开始计数
void sieve(int n)
notpri[1] = 1;
for(int i = 2; i <= n; i++)
if(!notpri[i])
pri[++pritop] = i;
for(int j = 1; j <= pritop && i * pri[j] <= n; j++)
notpri[i * pri[j]] = 1;
if(i % pri[j] == 0)
break;
printf("ptop=%d\n", pritop);
vector<ll> H;
int main()
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
sieve(MAXN);
for(int i = pritop; i >= pritop - 100; --i)
for(int j = i - 1; j >= i - 1 - 100; --j)
H.push_back(1ll*pri[i]*pri[j]);
sort(H.begin(),H.end(),greater<ll>());
for(int i=0;i<100;++i)
printf("i=%d num=%lld\n",i+1,H[i]);
return 0;
可以看到这样的极端合数之间的间隔非常大!两个之间差了1e6以上!
ptop=664579
i=1 num=99999640000243
i=2 num=99999620000261
i=3 num=99999440000783
i=4 num=99999340000513
i=5 num=99999280000567
i=6 num=99999220000621
i=7 num=99999200000639
i=8 num=99999160001539
i=9 num=99999140001653
i=10 num=99999100001701
i=11 num=99999080001827
i=12 num=99999040001863
i=13 num=99999020002001
i=14 num=99999020001917
i=15 num=99999000002059
i=16 num=99998980000837
i=17 num=99998920000891
i=18 num=99998800003591
i=19 num=99998800002511
i=20 num=99998800000999
假如把三个不同质数的乘积也放上来,基本也是没有缩小到哪里。
所以可以猜测,在一次暴力验证的过程中,在找到Q之前,遇到的极端合数的数量估计不会超过10个,甚至不会超过5个。其他的合数的素因子很容易被判断掉了,几乎只是暴力判Q的零头,忽略不计。
质数之间的间隔的话,根据质数的总数量,平均是32个出现一个,当然在比较大的时候间隔较远,但是我猜测不会超过1000,连续1000个数都没有质数的,希望大佬给出一个估计?
那么大概暴力判一次Q,最差情况在6e6左右,考虑T比较小(后面题面改来改去差评),直接暴力。
根据猜测的结果(威尔逊定理):(P-2)! = 1 mod P ,每次两边乘两个个逆元也可以转移到下一个数,至多转移1000次,1000log1e14也是零头,忽略不计。
最后要小心溢出,改了很多地方,乘逆元的地方都改了__int128但是快速幂里面没改,导致溢出WA1,太坑了。
其实只是使用乘法取模,可以用快速乘的。
以上是关于2019 Multi-University Training Contest 3 - 1006 - Fansblog - 打表 - 暴力的主要内容,如果未能解决你的问题,请参考以下文章
2019 Multi-University Training Contest 6
2019 Multi-University Training Contest 6
2019 Multi-University Training Contest 6
2019 Multi-University Training Contest 3