题解 | #牛牛的函数#

牛牛的函数

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

描述

这是一篇面对初级coder的题解。
知识点:数学 快速幂 等比数列 费马小定理
难度:三星


题解

题目:
定义函数 ,然后在给定a和b的情况下,求f(x)%10000000033的值。
分析:

首先需要用等比数列的求和公式对
计算乘方可采用
中的快速幂算法

方法一:直接计算

之前的乘方算法化简到最简单依旧需要计算两个大数乘法
long long 是8字节 两个long long相乘就到了是16字节,同时由于由于取模运算的模太大所以必须对乘法进行处理,否则乘法溢出!

类比竖式乘法:设计如下乘法逻辑,对每步乘法运算取模 保证乘法不溢出:
class Solution {
    const long long mod=10000000033LL;//取余常数
public:
    long long power(long long base, long long exponent) {
        if(exponent==0)
            return 1;
        long long answer = 1;
        while(exponent){
            if(exponent&1)        //如果n的当前末位为1
                answer =multi(answer,base);  //ans乘上当前的a
            base =multi(base,base);        //a自乘
            exponent >>= 1;       //n往右移一位
        }
        return answer;
    }
    long long multi(long long a, long long b) {//防止越界 乘法 每次只乘2字节
        long long ans =0;
        while(b){
            ans=(ans+a*(b&0xFFFFLL))%mod;//相乘累加
            b>>=16;//乘数右移2字节
            a=(a<<16)%mod;//被乘数左移2字节
        }
        return ans;
    }

    long long solve(int a, int b, int n) {
        if(n==0)
            return 0; //处理特殊情况
        long long ans=0;
        for(int i=a;i<=b;i++){
            ans+=power((long long)n,(long long)i) % mod;//按要求相加
            ans =ans % mod;
        }
        return ans;
    }
};
复杂度分析:
时间复杂度:快幂法的时间复杂度都是,同时由于没有做优化,总共需要进行次幂运算,所以时间复杂度为 
此处 
空间复杂度 ,由于没有使用额外的空间 空间复杂度为 
运行测试:
运行超时
运行时间1001ms 占用内存404KB

方法二:等比数列求和公式+费马小定理

考虑等比数列求和公式

但是其中的除法  难以取模 所以这里需要用到费马小定理求逆元
在这样的基础上,推导


根据等比数列公式有

根据上面的费马小定理有
即:
代入上式得
程序中记:

则所求

class Solution {
    const long long mod=10000000033LL;//取余常数
public:
    long long power(long long base, long long exponent) {
        if(exponent==0)
            return 1;
        long long answer = 1;
        while(exponent){
            if(exponent&1)        //如果n的当前末位为1
                answer =multi(answer,base);  //ans乘上当前的a
            base =multi(base,base);        //a自乘
            exponent >>= 1;       //n往右移一位
        }
        return answer;
    }
    long long multi(long long a, long long b) {//防止越界 乘法 每次只乘2字节
        long long ans =0;
        while(b){
            ans=(ans+a*(b&0xFFFFLL))%mod;//相乘累加
            b>>=16;//乘数右移2字节
            a=(a<<16)%mod;//被乘数左移2字节
        }
        return ans;
    }
    long long solve(int a, int b, int n) {
        if(n==0)
            return 0; //处理特殊情况
        if(n == 1)//用费马小定理那步要求n!=1
            return b - a + 1;//直接返回n=1值
        long long a1=power((long long)n,(long long)a);
        long long anq=power((long long)n,(long long)(b+1));
        long long np=power((long long)n-1,(long long)(mod-2));
        return multi(anq-a1+mod,np);
        // write code here
    }
};
复杂度分析:
时间复杂度:快幂法的时间复杂度都是,同时由于采用费马小定理和等比数列求和公式做了优化,总共需要进行3次幂运算,

 
空间复杂度:由于没有使用额外的空间 空间复杂度为 
运行测试:
运行时间: 3 ms 占用内存:400K

总结

数学知识很重要
阿Q的题解 文章被收录于专栏

阿Q秋招刷过的题

全部评论

相关推荐

刚刷到字节跳动官方发的消息,确实被这波阵仗吓了一跳。在大家还在纠结今年行情是不是又“寒冬”的时候,字节直接甩出了史上规模最大的转正实习计划——ByteIntern。咱们直接看几个最硬的数,别被花里胡哨的宣传词绕晕了。首先是“量大”。全球招7000多人是什么概念?这几乎是把很多中型互联网公司的总人数都给招进来了。最关键的是,这次的资源分配非常精准:研发岗给了4800多个Offer,占比直接超过六成。说白了,字节今年还是要死磕技术,尤其是产品和AI领域,这对于咱们写代码的同学来说,绝对是今年最厚的一块肥肉。其次是大家最关心的“转正率”。官方直接白纸黑字写了:整体转正率超过50%。这意味着只要你进去了,不划水、正常干,每两个人里就有一个能直接拿校招Offer。对于2027届(2026年9月到2027年8月毕业)的同学来说,这不仅是实习,这简直就是通往大厂的快捷通道。不过,我也得泼盆冷水。坑位多,不代表门槛低。字节的实习面试出了名的爱考算法和工程实操,尤其是今年重点倾斜AI方向,如果你简历里有和AI相关的项目,优势还是有的。而且,转正率50%也意味着剩下那50%的人是陪跑的,进去之后的考核压力肯定不小。一句话总结:&nbsp;27届的兄弟们,别犹豫了。今年字节这是铁了心要抢提前批的人才,现在投递就是占坑。与其等到明年秋招去千军万马挤独木桥,不如现在进去先占个工位,把转正名额攥在手里。
喵_coding:别逗了 50%转正率 仔细想想 就是转正与不转正
字节7000实习来了,你...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务