本题关键——费马小定理

牛牛的函数

http://www.nowcoder.com/questionTerminal/9d90c461f30e46d29500fbc0d9a24634

首先看到题目我选择了暴力加法,结果毫无疑问地超时了......
接着看别人的代码再自己查资料, 我有了思路

从n的a次方累加到n的b次方可以用等比数列求和公式得到 f(n) = (n^(b+1) - n^a)/(n-1)
要求f(n) % 10000000033, n-1是一个很麻烦的地方,由此我找到了一个数学定理————费马小定理
费马小定理讲的是如果p是一个质数,而整数x不是p的倍数,则有x^(p-1)%p = 1;
这里10000000033是一个质数,而n-1显然不是其倍数,满足条件
两边同时除以x得到x^(p-2) % p = 1/x % p;
即(y/x)%p = y%p * (1/x)%p = y%p * x^(p-2)%p;
(这里令p=10000000033, y = n^(b+1)-b^a, x=n-1)

解决了这一个问题,下一个问题来了,要是a和b的值很大,那么来求n^(b+1)而保证不超出long long的限制呢
看大神们的代码,我知道了快速幂的方法

在以上的基础上,我发现我的代码还是不能AC,又上网查了一下,才知道在我的快速幂计算过程中还是可能会超过long long的限制,还需要使用快速乘法来得到余数。

#define ll long long
const ll MOD=10000000033;
class Solution
{
    public:
    //快速乘法
        ll ksc(ll x,ll y)
        {
            return (x*y-(ll)((long double)x/MOD*y)*MOD+MOD)%MOD;
        }
    //快速幂
        ll quickPow(int x,ll b)
        {
            ll base=x,res=1;
            while(b)
            {
                if(b&1) res=ksc(res,base);
                b>>=1;
                base=ksc(base,base);
            }
            return res;
        }
        long long solve(int a,int b,int n)
        {
            if(n==0) return 0;
            if(n==1) return b-a+1;
            ll res=(quickPow(n,b+1)-quickPow(n,a)+MOD)%MOD;
            //费马小定理求逆元
            ll inv=quickPow(n-1, MOD-2);
            return ksc(res,inv);
        }
};
全部评论
(y/x)%p = y%p * (1/x)%p = y%p * a^(x-2)%p; 没看懂这一步怎么变换来的,怎么就把(1/x)换成了a^(x-2)呢?
点赞 回复 分享
发布于 2020-07-15 22:18
ll inv=quickPow(n-1,Mod-2)这里按照推论(1/x)%Mod=x^(Mod-2),不是应该是quickPow(n,Mod-1)吗,还有快速乘法那里x*y直接会爆吧,x,y最大1e10
点赞 回复 分享
发布于 2020-07-22 09:52

相关推荐

球球别再泡了:坏,我单9要了14
点赞 评论 收藏
分享
ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
评论
4
收藏
分享
牛客网
牛客企业服务