http://code.google.com/codejam/contest/dashboard?c=32016#s=p2
Problem
In this problem, you have to find the last three digits before the decimal point for the number (3 + √5)n.
For example, when n = 5, (3 + √5)5 = 3935.73982... The answer is 935.
For n = 2, (3 + √5)2 = 27.4164079... The answer is 027.
Input
The first line of input gives the number of cases, T. T test cases follow, each on a separate line. Each test case contains one positive integer n.
Output
For each input case, you should output:
Case #X: Y
where
X is the number of the test case and
Y is the last three integer digits of the number (3 + √5)
n. In case that number has fewer than three integer digits, add leading zeros so that your output contains exactly three digits.
Limits
1 <= T <= 100
Small dataset
2 <= n <= 30
Large dataset
2 <= n <= 2000000000
Sample
Input |
Output |
2 5 2
|
Case #1: 935 Case #2: 027
|
Analysis
Solving the large tests was a very different problem. The difficulty comes from the fact that √5 is irrational and for n close to 2000000000 you would need a lot of precision and a lot of time if you wanted to use the naive solution.
The key in solving the problem is a mathematical concept called conjugation. In our problem, we simply note that (3 - √5) is a nice conjugate for (3 + √5). Let us define
(1) α := 3 + √5, β := 3 - √5, and Xn := αn + βn.
We first note that X
n is an integer. This can be proved by using the
binomial expansion. If you write everything down you'll notice that the irrational terms of the sums cancel each other out.
Another observation is that β
n < 1, so X
n is actually the first integer greater than α
n. Thus we may just focus on computing the last three digits of X
.
A side note. In fact, βn tends to 0 so quickly that that our problem would be trivial if we asked for the three digits after the decimal point. For all large values of n they are always 999.
SO, the last three digits of Xn-1 is what we want. We also know that X
(n)=6X(n-1)-4X(n-2),X(0)=2,X(1)=6,so we can calc Xn easily.
code
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
const int mod=1000;
struct Matrix
{
int m[4];
};
Matrix matrix,unit;
Matrix operator*(const Matrix & m1,const Matrix & m2)
{
Matrix res;
res.m[0]=(m1.m[0]*m2.m[0]+m1.m[1]*m2.m[2]+1000000)%mod;
res.m[1]=(m1.m[0]*m2.m[1]+m1.m[1]*m2.m[3]+1000000)%mod;
res.m[2]=(m1.m[2]*m2.m[0]+m1.m[3]*m2.m[2]+1000000)%mod;
res.m[3]=(m1.m[2]*m2.m[1]+m1.m[3]*m2.m[3]+1000000)%mod;
return res;
}
Matrix power(int n)
{
Matrix res;
if(n<=0)
{
return unit;
}
if(n==1)
return matrix;
res = power(n/2);
res = res * res;
if(n%2)
res=res*matrix;
return res;
}
int solve(int n)
{
matrix.m[0]=6,matrix.m[1]=-4,matrix.m[2]=1,matrix.m[3]=0;
unit.m[0]=1,unit.m[1]=0,unit.m[2]=0,unit.m[3]=1;
Matrix res=power(n-1);
return (res.m[0]*6+res.m[1]*2+999+1000000)%mod;
}
int main()
{
int t,n;
//freopen("C-small-practice.in","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
scanf("%d",&n);
printf("Case #%d: %03d\n",cas,solve(n));
}
}