2018.9.7南海中学测试T1(等比数列二分求和)

A病毒分裂
Time Limit:10000MS Memory Limit:165536K
Case Time Limit:1000MS
Description
A 学校的实验室新研制出了一种十分厉害的病毒。由于这种病毒太难以人工制造了,所以专家们在一开始只做出了一个这样的病毒。
这个病毒被植入了特殊的微型芯片,使其可以具有一些可编程的特殊性能。最重要的一个性能就是,专家们可以自行设定病毒的分裂能力K,假如现在有x 个病毒,下一个分裂周期将会有Kx 个一模一样的病毒。你作为该实验室的数据分析员,需要统计出在分裂到第N 个周期前,一共有多少个病毒单体进行了分裂。一开始时总是只有一个病毒,这个局面算作第一个周期。由于答案可能很大,专家们只需要你告诉他们对给定的P 取模后的答案。
Input
一行三个整数,依次是K, N, P。
Output
一行一个整数,你的答案(对P 取模) 。
Sample Input
【样例输入1】
5 3 7
【样例输入2】
2 6 23
Sample Output
【样例输出1】
6
【样例输出2】
8

这道题目,模拟一下就会发现,就是等比数列求和。首先想到要用的东西就是快速幂,毕竟可以使用快速幂来暴力。

所以一开始我先打了一个O(n)的暴力算法:

#include<iostream>
#include<stdio.h>
using namespace std;
long long k,n,p,d=1,and_;
void read();
int main()
{
    read();
    for(long long i=1;i<n;i++)
    {
        and_+=d;
        and_%=p;
        d*=k;
        d%=p;
    }
    if(and_==0)
      and_=1;
    printf("%lld",and_%p);
    return 0;
}
void read()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%lld%lld%lld",&k,&n,&p);
    return ;
}

然后,不知不觉,就AC了!
数据特别水,所以就AC了。然后很多人说要用逆元,他们做错了,所以就特别不爽我们这些用O(n)拿满分的人;
然后,我们可敬的cmb指导老师就说出了好多句金句:
“呵呵,noip多次证明水分的重要性”
“事实证明不屑水分的人都被分数所不屑”
“所以,认真贯彻比赛纪律,水分对拍正解。”

所以听从老师的指导,以后我都水分出来先hhhh。


然而一直水分也不是好的,现在就讲讲这道题目的正解吧。

这道题用了一个很厉害的一个公式: 等比数列二分求和

当n==0时,S=1;

当n%2==0时,也就是n为偶数时:

当n%2==1时,也就是n为奇数时:

其实,仔细认真推一下,是可以推出来的,贴上我的代码:

long long solve(long long k,long long n)
{
    if(n==1)return k%p;
    int t=solve(k,n/2);
    if(n&1)
    {
        long long t1=doit(k,n/2),t2=doit(k,n);
        t=(t+t1*t%p+t2)%p;
    }
    else
    {
        long long t1=doit(k,n/2);
        t=(t+t1*t%p)%p;
    }
    return t%p;
}

然后就是这道题目,只要仔细认真读好题目,知道求的是什么,那么稍作修改,就可以AC了。

贴上代码:

#include<iostream>
#include<stdio.h>
using namespace std;
long long k,n,p,d,S;
void read();
long long doit(long long k,long long n) {
    if(n==1)  return k%p;
    long long t=doit(k,n/2);
    long long ans=t*t%p;
    if(n%2==1)  ans=ans*k%p;
    return ans;
}
long long solve(long long k,long long n)
{
    if(n==1)return k%p;
    int t=solve(k,n/2);
    if(n&1)
    {
        long long t1=doit(k,n/2),t2=doit(k,n);
        t=(t+t1*t%p+t2)%p;
    }
    else
    {
        long long t1=doit(k,n/2);
        t=(t+t1*t%p)%p;
    }
    return t%p;
}
int main()
{
    read();
    S=solve(k,n-2)+1;
    printf("%I64d",S%p);
    return 0;
}
void read()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%I64d%I64d%I64d",&k,&n,&p);
    return ;
}

最后,注意一点:long long! long long! long long!

全部评论

相关推荐

不愿透露姓名的神秘牛友
04-30 11:43
春招失败、父母离婚,好像我的人生一团糟,一年来压力大到常常崩溃。不知道能跟谁聊,朋友其实对我非常好,但是她无意中表达出来的家庭幸福都会刺痛到我……和ai聊天,我的未来在更高处,不在楼下,忍不住爆哭😭
youngfa:害,妹妹,我是一个研究生(很上进很想找到好工作的那种),但去年因为生病回家休养错过了秋招(当时对我的冲击也是非常大的),这学期返校来了也是把论文盲审交了后才开始找工作,现在也是一个offer没有,但我就没有像你一样把这个阶段性的事情绑定到人生上,人生不仅很长,也很广阔,先停下来,放松一下哦。不要被外部环境灌输的思维操控了,好好爱自己!
点赞 评论 收藏
分享
AI牛可乐:哇塞,恭喜恭喜!48万的年薪,真是让人羡慕呀!看来你找到了一个超棒的工作,可以享受不卷的生活啦!🎉有没有什么求职秘诀想要分享给小牛牛呢?或者,想不想知道我是谁呢?😉(点击我的头像,我们可以私信聊聊哦~)
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务