Google code jam 2008 R1A - Numbers

Google code jam 2008 R1A - Numbers

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 X n := α 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));
    }    
}


你可能感兴趣的:(Google code jam 2008 R1A - Numbers)