【问题描述】
(如果你想更好地理解本题,请先阅读 NOI2011 第一试“兔农”一题)
萌蛋近年收入不景气,正在她发愁如何能多赚点钱时,她听到隔壁的小朋友在讨论免子繁殖的问题。(注:免子是一种简单的单细胞生物)
问题是这样的:时刻 0 有 2 只刚出生的免子。每一时刻,每只免子都会分裂成为 2 只免子。问时刻??共有多少只免子?
聪明的你可能已经发现,时刻??的免子数正好是第?? + 1个 2 的幂次。萌蛋不懂什么叫幂,但她也发现了规律:时刻?? + 1的免子数等于时刻??的免子数的 2 倍。前几个时刻(从 0 开始)的免子数依次为:
2 4 8 16 32 64 128 256 512 …
萌蛋发现越到后面免子数增长的越快,期待养免子一定能赚大钱,于是萌蛋在时刻 0 买了 2 只免子开始培养。
每天,萌蛋都要给免子们提供营养。免子的培养基非常特别,每??只免子占据一个培养基,最后剩下的不足??只占据一个培养基。由于免子特别害怕孤独, 如果某个培养基只有 1 只免子,这只免子就会很快死掉。
然而,每个时刻的免子数仍然是可以计算的。例如,当?? = 7时,前几个时刻(从 0 开始)的免子数依次为:
2 4 7 14 28 56 112 224 448 …
给定??,你能帮助萌蛋计算时刻??她有多少只免子么?由于答案可能非常大, 你只需要告诉萌蛋时刻??的免子只数对??的余数即可。
【输入文件】
输入只有一行,包含三个整数?? ?? ??。
【输出文件】
输出只有一行,为一个整数,表示时刻??的免子只数对??的余数。
【输入样例】
6 7 10086
【输出样例】
112
【数据规模和约定】
对于 30%的数据,?? ≤ 1,000,000。另有 30%的数据,??是??的正整数倍。
对于 100%的数据,?? ≤ 1,000,000,000, 2 ≤ ?? ≤ 1,000,000,1 ≤ ?? ≤ 1,000,000。
分析
题解原话
对于如果k是偶数兔子不会死去的证明:
设n为兔子的只数,有一只兔子死去的条件是n mod k=1;
转换一下就是 n-t*k=1; n=1+t*k; 如果k是偶数的话,它的倍数也是偶数,偶数+1是奇数,而兔子只数是偶数,所以当k时偶数时不会有兔子死亡.
代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } int n,k,p; int power(int x) { int res=1,base=2; while(x) { if(x&1) res=(ll)res*(ll)base%(ll)p; base=(ll)base*(ll)base%(ll)p; x=x>>1; } return res; } int main() { freopen("rabit.in","r",stdin); freopen("rabit.out","w",stdout); n=read();k=read();p=read(); if(k&1) { int ak=2,ap=2; while(n--) { ak=(ll)ak*(ll)2%(ll)k; ap=(ll)ap*(ll)2%(ll)p; if(ak==1) { ap=(ap-1+p)%(ll)p;//ap-1有可能<=0,所以要加上p ap=(ll)ap*(ll)power(n)%(ll)p; printf("%d\n",ap); return 0; } } printf("%d\n",ap); } else printf("%d\n",power(n+1)); return 0; }