BZOJ5104 Fib数列(二次剩余+BSGS)
5在1e9+9下有二次剩余,那么fib的通项公式就有用了。
已知Fn,求n。注意到[(1+√5)/2]·[(1-√5)/2]=-1,于是换元,设t=[(1+√5)/2]n,原式变为√5·Fn=t-(-1)n·t-1。同乘t并移项,可得t2-√5·Fn·t-(-1)n=0。讨论n的奇偶性,BSGS求二次剩余大力解方程即可。用BSGS求二次剩余是非常简单的,求出其以原根为底的离散对数即可。
注意二次剩余有正负两解,但似乎代进去正根(即√gk=gk/2)就行了,不太明白。以及题目要求最小解,BSGS的时候注意顺序。还有BSGS不一定有解,我也不知道我在BSGS里面assert了半天是在干啥。调了一年惨炸了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#include<cassert>
using namespace std;
#define ll long long
#define P 1000000009
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,b,g,v,ans=P;
map<int,int> f;
int ksm(int a,int k)
{
int s=;
for (;k;k>>=,a=1ll*a*a%P) if (k&) s=1ll*s*a%P;
return s;
}
int inv(int a){return ksm(a,P-);}
int BSGS(int g,int k)
{
f.clear();
int block=sqrt(P),t=ksm(g,block),x=,ans=-;g=inv(g);
for (int i=;i<block;i++)
{
if (f.find(1ll*x*k%P)==f.end()) f[1ll*x*k%P]=i;
x=1ll*x*g%P;
}
x=;
for (int i=;i<P;i+=block)
{
if (f.find(x)!=f.end()) {ans=f[x]+i;break;}
x=1ll*x*t%P;
}
return ans;
}
int SQRT(int n)
{
int k=BSGS(g,n);
if (k==-||k&) return -;
return ksm(g,k>>);
}
void solve(int c,int op,int op2)
{
int delta=SQRT(((1ll*b*b-4ll*c)%P+P)%P);
if (delta==-) return;
delta=(P+op2*delta)%P;
int ans1=1ll*((delta-b)%P+P)%P*inv()%P,ans2=1ll*((-delta-b)%P+P)*inv()%P;
ans1=BSGS(v,ans1),ans2=BSGS(v,ans2);
if ((ans1&)==op&&ans1>) ans=min(ans,ans1);
if ((ans2&)==op&&ans2>) ans=min(ans,ans2);
}
int fib(int n)
{
struct matrix
{
int n,a[][];
matrix operator *(const matrix&b) const
{
matrix c;c.n=n;memset(c.a,,sizeof(c.a));
for (int i=;i<n;i++)
for (int j=;j<;j++)
for (int k=;k<;k++)
c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j])%P;
return c;
}
}f,a;
f.n=;f.a[][]=,f.a[][]=;
a.n=;a.a[][]=,a.a[][]=a.a[][]=a.a[][]=;
for (;n;n>>=,a=a*a) if (n&) f=f*a;
return f.a[][];
}
void work(int sqrt5)
{
b=(P-1ll*sqrt5*n%P)%P;
v=1ll*(sqrt5+)*inv()%P;
solve(P-,,),solve(,,);
//solve(P-1,0,-1),solve(1,1,-1);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5104.in","r",stdin);
freopen("bzoj5104.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
/*for (int i=2;;i++)
{
bool flag=1;
for (int j=2;j*j<P;j++)
if ((P-1)%j==0)
{
if (ksm(i,j)==1) {flag=0;break;}
if (ksm(i,(P-1)/j)==1) {flag=0;break;}
}
if (flag) {g=i;break;}
}*/
g=;
n=read();
work(SQRT());//,work(P-SQRT(5));
if (ans==P) cout<<-;else assert(fib(ans)==n),cout<<ans;
return ;
}
BZOJ5104 Fib数列(二次剩余+BSGS)的更多相关文章
- BZOJ5104 Fib数列 二次剩余、BSGS
传送门 发现只有通项公式可以解决考虑通项公式 \(F_n = \frac{1}{\sqrt{5}}((\frac{1+\sqrt{5}}{2})^n - (\frac{1-\sqrt{5}}{2})^ ...
- bzoj5104 Fib数列(BSGS+二次剩余)
快AFO了才第一次写二次剩余的题…… 显然应该将Fn写成通项公式(具体是什么写起来不方便而且大家也都知道),设t=((1+√5)/2)n,T=√5N,然后可以得到t-(-1)t/t=√5N,两边同时乘 ...
- 【BZOJ5104】Fib数列(BSGS,二次剩余)
[BZOJ5104]Fib数列(BSGS,二次剩余) 题面 BZOJ 题解 首先求出斐波那契数列的通项: 令\(A=\frac{1+\sqrt 5}{2},B=\frac{1-\sqrt 5}{2}\ ...
- bzoj5104: Fib数列
Description Fib数列为1,1,2,3,5,8... 求在Mod10^9+9的意义下,数字N在Fib数列中出现在哪个位置 无解输出-1 Input 一行,一个数字N,N < = 10 ...
- @bzoj - 5104@ Fib数列
目录 @description@ @solution@ @accepted code@ @details@ @description@ Fib数列为1,1,2,3,5,8... 求在Mod10^9+9 ...
- FIB数列
斐波那契级数除以N会出现循环,此周期称为皮萨诺周期. 下面给出证明 必然会出现循环 这是基于下面事实: 1. R(n+2)=F(n+2) mod P=(F(n+1)+F(n)) mod P=(F(n+ ...
- 动态规划之Fib数列类问题应用
一,问题描述 有个小孩上楼梯,共有N阶楼梯,小孩一次可以上1阶,2阶或者3阶.走到N阶楼梯,一共有多少种走法? 二,问题分析 DP之自顶向下分析方式: 爬到第N阶楼梯,一共只有三种情况(全划分,加法原 ...
- UVaLive 3357 Pinary (Fib数列+递归)
题意:求第 k 个不含前导 0 和连续 1 的二进制串. 析:1,10,100,101,1000,...很容易发现长度为 i 的二进制串的个数正好就是Fib数列的第 i 个数,因为第 i 个也有子问题 ...
- 【bzoj5118】Fib数列2 费马小定理+矩阵乘法
题目描述 Fib定义为Fib(0)=0,Fib(1)=1,对于n≥2,Fib(n)=Fib(n-1)+Fib(n-2) 现给出N,求Fib(2^n). 输入 本题有多组数据.第一行一个整数T,表示数据 ...
随机推荐
- 关于判断用户输入的是不是int类型,这次没有正则表达式
末尾没有目的地的出租车,污点证人禁止入内!!! 不同的尝试有不同的方法 关于int类型的判断,我尝试了这么一个方法,可行,只是笨 正则表达式我没有搞清楚,没办法给大家讲解,欢迎各位明白人讲解,或者是我 ...
- Mac电脑如何快速下载YouTube视频
如果你想下载一些教育类的视频资源,或者是一些学习的教程,那么YouTube是一个很好的视频资源平台.YouTube上面各种各样的资源都有,而且质量都很有保证,尤其是那些订阅量很多的人.可惜的是,You ...
- 关于matlab向文件写入数据的方法——留着备用
MATLAB数据采集的时候,往往需要把得到的数据保存下来. fid = fopen(文件名,‘打开方式’): 说明:fid用于存储文件句柄值,如果fid>0,这说明文件打开成功.打开方式有如下选 ...
- (1) Python 数据类型功能
1.int 将字符串转化为数字 a="123" print(type(a),a) b=int(a) print(type(b),b) num="0011" ...
- 2015第六届蓝桥杯C/C++ B组
奖券数目:枚举 有些人很迷信数字,比如带“4”的数字,认为和“死”谐音,就觉得不吉利.虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求.某抽奖活动的奖券号码是5位数(10000-99999),要求其 ...
- Linux(Contos7.5)环境搭建之JDK1.8安装(二)
1.下载安装包 wget -p 目录 url包地址 2.解压安装包 tar -xzvf 文件 -C 指定目录 3.修改名称 mv jdk1.8.0_45 jdk1.8 4.配置环境变量 vim /e ...
- 查看linux端口对应的进程id
例如:查看占用4040端口的进程 ss -lptn 'sport = :4040'
- 满帮集团CEO:未来将向“智慧型”公司转变,要成为一家生态公司
谁都想成为下一个滴滴.显然,王刚也希望在物流业,货车帮与运满满在合并后,能够企及滴滴的高度. 货车帮与运满满,都曾是货运物流领域的翘楚,也因为业务的竞争关系有过水火不容厮杀.但最终还是在资本与地方政府 ...
- M1个人贡献分以及转会确定
按照之前的方案,团队成员得分统计表见下: P(Pd*pf) 比重 个人得分 黎柱金 335400 0.1844 63 晏旭瑞 306000 0.1682 59 孙思权 304150 0.1672 ...
- java第二次实验报告20135231
Java实验报告二:Java面向对象程序设计 20135231 何佳 实验要求: 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉 ...