本题关键——费马小定理

牛牛的函数

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

相关推荐

小红书 后端开发 总包n+8w+期权
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-26 18:54
点赞 评论 收藏
分享
沉淀一会:1.同学你面试评价不错,概率很大,请耐心等待; 2.你的排名比较靠前,不要担心,耐心等待; 3.问题不大,正在审批,不要着急签其他公司,等等我们! 4.预计9月中下旬,安心过节; 5.下周会有结果,请耐心等待下; 6.可能国庆节前后,一有结果我马上通知你; 7.预计10月中旬,再坚持一下; 8.正在走流程,就这两天了; 9.同学,结果我也不知道,你如果查到了也告诉我一声; 10.同学你出线不明朗,建议签其他公司保底! 11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
4 收藏 评论
分享
牛客网
牛客企业服务