标签:
(如果你想更好地理解本题,请先阅读NOI2011第一试“兔农”一题)
萌蛋近年收入不景气,正在她发愁如何能多赚点钱时,她听到隔壁的小朋友在讨论免子繁殖的问题。(注:免子是一种简单的单细胞生物)
问题是这样的:时刻0有2只刚出生的免子。每一时刻,每只免子都会分裂成为2只免子。问时刻n共有多少只免子?
聪明的你可能已经发现,时刻n的免子数正好是第n+1个2的幂次。萌蛋不懂什么叫幂,但她也发现了规律:时刻n+1的免子数等于时刻n的免子数的2倍。前几个时刻(从0开始)的免子数依次为:
2 4 8 16 32 64 128 256 512 …
萌蛋发现越到后面免子数增长的越快,期待养免子一定能赚大钱,于是萌蛋在时刻0买了2只免子开始培养。
每天,萌蛋都要给免子们提供营养。免子的培养基非常特别,每k只免子占据一个培养基,最后剩下的不足k只占据一个培养基。由于免子特别害怕孤独,如果某个培养基只有1只免子,这只免子就会很快死掉。
然而,每个时刻的免子数仍然是可以计算的。例如,当k=7时,前几个时刻(从0开始)的免子数依次为:
2 4 7 14 28 56 112 224 448 …
给定n,你能帮助萌蛋计算时刻n她有多少只免子么?由于答案可能非常大,你只需要告诉萌蛋时刻n的免子只数对p的余数即可。
输入只有一行,包含三个整数n k p。
输出只有一行,为一个整数,表示时刻n的免子只数对p的余数。
6 7 10086
112
对于30%的数据,n≤1,000,000。
另有30%的数据,k是p的正整数倍。
对于100%的数据,n≤1,000,000,000,2≤k≤1,000,000,1≤p≤1,000,000。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<string> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<set> using namespace std; #define INF 1<<30 #define LL long long LL n,k,p; LL pow(LL x) { LL ans=1,y=2; while(x) { if(x&1) ans=ans*y%p; y=(y*y)%p; x=x>>1; } return ans%p; } int main() { scanf("%I64d%I64d%I64d",&n,&k,&p); LL ans=2,tem=2; if(k%2==0) { printf("%I64d\n",2*pow(n)); return 0; } for(int i=1;i<=n;i++) { tem=(tem*2)%k; if(tem%k==1) { printf("%I64d\n",(ans*2-1)*pow(n-i)%p); return 0; } ans=(ans*2)%p; } printf("%I64d\n",ans); return 0; }
标签:
原文地址:http://www.cnblogs.com/a972290869/p/4190874.html