zoukankan      html  css  js  c++  java
  • 2019 Multi-University Training Contest 3

    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
    ", 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
    ",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,太坑了。

    其实只是使用乘法取模,可以用快速乘的。

  • 相关阅读:
    easyui datetimebox 日期控件绑定双击日期选择时间
    js 中call和apply的应用
    js中数组的合并和对象的合并
    flex也可以让背景透明
    收集了一些as的面试题,给HR准备的
    [转]PureMVC的十个小提示
    12个Flex常用功能代码
    43个热门Flex和ActionScript 3.0 APIs,技巧和工具[转]
    转载+原创PureMVC 实例讲解
    PureMVC使用时的注意事项
  • 原文地址:https://www.cnblogs.com/Yinku/p/11267358.html
Copyright © 2011-2022 走看看