斐波那契变题
标题:斐波那契
斐波那契数列大家都非常熟悉。它的定义是:
f(x) = 1 … (x=1,2)
f(x) = f(x-1) + f(x-2) … (x>2)对于给定的整数 n 和 m,我们希望求出:
f(1) + f(2) + … + f(n) 的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
公式参见【图1.png】但这个数字依然很大,所以需要再对 p 求模。
【数据格式】
输入为一行用空格分开的整数 n m p (0 < n, m, p < 10^18)
输出为1个整数例如,如果输入:
2 3 5
程序应该输出:
0再例如,输入:
15 11 29
程序应该输出:
25资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 2000ms请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
方法一:
解析:
f(x) = f(x-1)+f(x-2)–>f(x+1)=f(x)+f(x-1)–>f(x+1)-f(x-1)
Σf(n) = f(n+2)-1
原题目等价于:(f(n+2)-1)%f(m)%p --> m>=n+2,余f(m)无意义
–>(f(n+2)-1)%p
(f(n+2)-1)%f(m)%p --> m<n+2
代码:
public class T9斐波那契 {
static int n;
static int m;
static int p;
static Long[] longs;
private static BigInteger fib(int k) {
for(int i=3;i<=k;i++){
longs[i]=longs[i-1]+longs[i-2];
}
return BigInteger.valueOf(longs[k]);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
p = scanner.nextInt();
longs = new Long[n+3];
longs[1]=Long.valueOf(1);
longs[2]=Long.valueOf(1);
BigInteger sum=fib(n+2);
if(m>=n+2) {
sum = sum.subtract(BigInteger.ONE);
sum = sum.mod(BigInteger.valueOf(p));
System.out.println(sum);
}else{
BigInteger numB = BigInteger.valueOf(longs[m]);
sum = sum.mod(numB);
sum = sum.mod(BigInteger.valueOf(p));
sum = sum.subtract(BigInteger.ONE);
}
System.out.println(sum);
}
}
但是本方法对于10^18次方的数据来说,一是超时,二是long无法存下这么大的数据,所以最终只能得40分
方法二:
解析
可以通过矩阵快速幂来得到结果,这是最快的解法 O(logn),用该方法可以解决超时问题
矩阵解法:
代码:
public class T9斐波那契2 {
static long n;
static long m;
static long p;
//矩阵相乘
public static M mul(M m1,M m2){
M ans = new M();
ans.data[0][0]=m1.data[0][0]*m2.data[0][0]+m1.data[0][1]*m2.data[1][0];
ans.data[0][1]=m1.data[0][0]*m2.data[0][1]+m1.data[0][1]*m2.data[1][1];
ans.data[0][1]=m1.data[1][0]*m2.data[0][0]+m1.data[0][1]*m2.data[1][0];
ans.data[0][1]=m1.data[1][0]*m2.data[0][1]+m1.data[0][1]*m2.data[1][1];
return ans;
}
//m的m次幂
public static M mPow(M m,long n){
M E = new M();//单位矩阵
E.data[0][0]=1;
E.data[0][1]=0;
E.data[1][1]=1;
E.data[1][0]=0;
while(n!=0){
if((n&1)==1){
E = mul(E,m);
}
m=mul(m,m);
n>>=1;
}
return E;
}
public static long fib(long i){
//[1,1]B^(i-2)
M A = new M();
A.data[0][0]=1;
A.data[0][1]=1;
A.data[1][0]=0;
A.data[1][1]=0;
M B = new M();
B.data[0][0]=1;
B.data[0][1]=1;
B.data[1][0]=1;
B.data[1][1]=0;
M ans = mul(A,mPow(B,i-2));
return ans.data[0][0];
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextLong();
m = scanner.nextLong();
p = scanner.nextLong();
}
static class M{
long data[][] = new long[2][2];
}
}