【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)
【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)
题面
题解
这题\(75\)分就是送的,我什么都不想写。
先手玩一下,发现每次每次出现\(mod\ K=1\)的数之后
把它减一,就变成了\(0\)。接着后面的数显然还是一个斐波那契数列
只是都乘了\(0\)之前的那个数作为倍数而已。
拿样例举个例子?以下数字都在模\(7\)意义下进行
1 1 2 3 5 0(1)
5 5 3 0(1)
3 3 6 2 0(1)
大概就是这样子。
当然,如果我们继续手玩下去,也许可以发现点什么?
1 1 2 3 5 0(1)
5 5 3 0(1)
3 3 6 2 0(1)
2 2 4 6 3 2 5 0
5 5 3 0(1)
似乎出现了循环???
那么,我们似乎可以按照找到末尾的\(0\),找下一行的零,找到循环节这样的步骤来。
至于这个循环节的长度相关的问题,可以看看Vfk的博客。orz
考虑一下怎么计算这个\(0\)的位置?事实上是在找\(1\)的位置
而上面举例中的每一行都是一个斐波那契数列乘上\(x\)
其中\(x\)是上一行中倒数第二个数字
那么,\(fib[len]*x=1\),而\(x\)对于我们来说是一个已知项
所以这个过程变成了一个求逆的过程。
而有根据\(vfk\)的博客,斐波那契数列在模\(K\)意义下的循环节长度不超过\(6K\)
所以我们可以暴力算一个循环节的斐波那契数列
这样子,我们的过程就变成了
找到当前行末尾的位置,对应的乘一下,得到下一行的倍数
如果下一行的开头这个数字已经被得到过,那么出现了全局的循环节,
直接暴力算就可以了。
如果发现此时逆元不存在,证明没有循环,直接矩阵快速幂即可。
否则的话继续矩阵快速幂找下一行即可。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 1001000
inline ll read()
{
RG ll x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
ll MOD;
void add(ll &x,ll y){x+=y;if(x>=MOD)x-=MOD;}
struct Matrix
{
ll s[4][4];
ll* operator[](int x){return s[x];}
void clear(){memset(s,0,sizeof(s));}
void init(){clear();s[1][1]=s[2][2]=s[3][3]=1;}
}nt,lt,ans,ret[MAX];
Matrix operator*(Matrix a,Matrix b)
{
Matrix ret;ret.clear();
for(int i=1;i<=3;++i)
for(int j=1;j<=3;++j)
for(int k=1;k<=3;++k)
add(ret[i][j],1ll*a[i][k]*b[k][j]%MOD);
return ret;
}
Matrix fpow(Matrix a,ll b)
{
Matrix s;s.init();
while(b){if(b&1)s=s*a;a=a*a;b>>=1;}
return s;
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b){x=1;y=0;return;}
exgcd(b,a%b,x,y);
ll tmp=y;
y=x-(a/b)*y;x=tmp;
}
ll f[MAX<<3],n,K,vis[MAX],inv[MAX],len[MAX];
bool book[MAX];
int main()
{
n=read();K=read();MOD=read();
f[1]=f[2]=1;bool fl=false;
for(int i=3;;++i)
{
f[i]=(f[i-1]+f[i-2])%K;
if(!vis[f[i]])vis[f[i]]=i;
if(f[i]==1&&f[i-1]==1)break;
}
nt[1][2]=nt[2][1]=nt[2][2]=nt[3][3]=1;
lt.init();lt[3][2]=-1;
ans[1][1]=ans[1][3]=1;
for(ll t=1;n;)
{
if(!inv[t])
{
if(__gcd(t,K)!=1)inv[t]=-1;
else
{
ll x,y;exgcd(t,K,x,y);
inv[t]=(x+K)%K;
}
}
if(inv[t]==-1){ans=ans*fpow(nt,n);break;}
if(!book[t]||fl)
{
book[t]=true;
if(!vis[inv[t]]){ans=ans*fpow(nt,n);break;}
len[t]=vis[inv[t]];
if(n>=len[t])
{
n-=len[t];
ret[t]=fpow(nt,len[t])*lt;
ans=ans*ret[t];
t=t*f[len[t]-1]%K;
}
else{ans=ans*fpow(nt,n);break;}
}
else
{
Matrix now;ll cnt=0;now.init();
for(ll i=t*f[len[t]-1]%K;i!=t;i=i*f[len[i]-1]%K)
now=now*ret[i],cnt+=len[i];
now=ret[t]*now;cnt+=len[t];
ans=ans*fpow(now,n/cnt);
n%=cnt;fl=true;
}
}
printf("%lld\n",(ans[1][2]%MOD+MOD)%MOD);
return 0;
}
【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)的更多相关文章
- [BZOJ2432][Noi2011]兔农 矩阵乘法+exgcd
2432: [Noi2011]兔农 Time Limit: 10 Sec Memory Limit: 256 MB Description 农夫栋栋近年收入不景气,正在他发愁如何能多赚点钱时,他听到 ...
- HDU 2256 Problem of Precision 数论矩阵快速幂
题目要求求出(√2+√3)2n的整数部分再mod 1024. (√2+√3)2n=(5+2√6)n 如果直接计算,用double存值,当n很大的时候,精度损失会变大,无法得到想要的结果. 我们发现(5 ...
- BZOJ2432 [Noi2011]兔农
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- 数论+矩阵快速幂|斐波那契|2014年蓝桥杯A组9-fishers
标题:斐波那契 斐波那契数列大家都非常熟悉.它的定义是: f(x) = 1 .... (x=1,2) f(x) = f(x-1) + f(x-2) .... (x>2) 对于给定的整数 n 和 ...
- 【BZOJ4002】[JLOI2015]有意义的字符串(数论,矩阵快速幂)
[BZOJ4002][JLOI2015]有意义的字符串(数论,矩阵快速幂) 题面 BZOJ 洛谷 题解 发现我这种题总是做不动... 令\(A=\frac{b+\sqrt d}{2},B=\frac{ ...
- cf 450b 矩阵快速幂(数论取模 一大坑点啊)
Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, ple ...
- HDU6395 Sequence(矩阵快速幂+数论分块)
题意: F(1)=A,F(2)=B,F(n)=C*F(n-2)+D*F(n-1)+P/n 给定ABCDPn,求F(n) mod 1e9+7 思路: P/n在一段n里是不变的,可以数论分块,再在每一段里 ...
- 数学--数论--HDU - 6395 Let us define a sequence as below 分段矩阵快速幂
Your job is simple, for each task, you should output Fn module 109+7. Input The first line has only ...
- 【数论】 快速幂&&矩阵快速幂
首先复习快速幂 #include<bits/stdc++.h> using namespace std; long long power(long long a,long long b,l ...
随机推荐
- python 内置模块(os)
1.OS os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径os.chdir("dirname") 改变当前脚本工作目录:相当于shell下cdos. ...
- 转:后台管理UI的选择
注:文中缺少了ZUI和LAYUI两个. 目录 一.EasyUI 二.DWZ JUI 三.HUI 四.BUI 五.Ace Admin 六.Metronic 七.H+ UI 八.Admin LTE 九.I ...
- bilibili携手WeTest,保障视频类应用优质适配体验
WeTest 导读 中国移动视频用户规模越来越大,各类移动视频APP也百家争鸣, B站作为国内知名的年轻人文化社区,bilibili在推出移动端时,除了坚持自身的独特定位以外,对其APP的质量也十分重 ...
- 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(中)
接<基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(上)> 三.代码分析 1.界面初始化 bool PlaneWarGame::init() { bool bRet = fals ...
- [转]WIN2008 IIS7的日期格式
最近项目升级服务器从32位升级到64位的WIN2008,日期显示格式非我们所期望的yyyy-M-d格式,原以为修改控制面板的日期格式即可,可是不行. 修改注册表问题解决. 修改方法: 运行注册表编辑器 ...
- 英特尔近日发布最新版实感™ SDK R5 (v7)
英特尔开发人员专区 原文地址 英特尔® 实感™ SDK 的 7.0.23.8048 版本(也称为 R5)现已推出.您将看到的主要变化包括: 支持英特尔® 实感™ SR300 摄像头:应于 2016 年 ...
- dalao自动报表邮件2.0
经过昨天的修改优化后,dalao收到了不是“木马”的邮件,欣慰地点了点头,“不错,不错,这几张表设计的简洁明了,看着有货!不过呀,,,这些表的数据太多了一点,十几天的数据一大溜,能不能再简洁一点,做一 ...
- ConcurrentHashMap(JDK1.8)为什么要放弃Segment
今天看到一篇博客:jdk1.8的HashMap和ConcurrentHashMap,我想起了前段时间面试的一个问题:ConcurrentHashMap(JDK1.8)为什么要使用synchronize ...
- mongodb windows 4 zip安装
安装mongoDB目的:学习Express,顺带mongodb. 本文目的: 4.0.2的mongodb在windows7上竟然安装不了. 没办法,用压缩包手动安装吧... 安装环境:win7sp1x ...
- day02——作业讲解
# 设定⼀个理想数字⽐如:66,让⽤户输⼊数字,如果⽐66⼤,则显示猜测# 的结果⼤了:如果⽐66⼩,则显示猜测的结果⼩了;只有等于66,显示猜测结果# 正确,然后退出循环 #升级版# 可以帮我们生成 ...