题目链接:hdu 5047
问n个M型的折线段最多能把一个平面分成多少个部分
通过数学推导可以发现结果为 8*n*n-7*n+1
本题的n的范围达到了10^12,连long long都爆了,队友准备直接java大数的结果这题卡时限卡的很紧,java会T。因此需要手敲高精度。
但是这题的数据范围最大只到10^24,因此可以用三个long long的分别表示从高到低的9位的数,然后敲高精度,能很好的降低代码的复杂度
/******************************************************
* File Name: 1006.cpp
* Author: kojimai
* Creater Time:2014年09月27日 星期六 14时36分54秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const long long mod= 1e9;
long long l1,l2,l3;
long long al,bl,cl;
void mul()
{
long long t1=0,t2=0,t3=0;
long long t;
t1=l1*l1;
t=t1/mod;
t1=t1%mod;
t2=l2*l1+t;
t=t2/mod;
t2=t2%mod;
t3+=t;
//cout<<"t3="<<t3<<" t2="<<t2<<" t1="<<t1<<endl;
t2+=l2*l1;
t=t2/mod;
t2%=mod;
t3+=l2*l2+t;
l1=t1;
l2=t2;
l3=t3;
}
void muln(int x)
{
l1=l1*x;
long long t=l1/mod;
l1%=mod;
l2=x*l2+t;
t=l2/mod;
l2%=mod;
l3=l3*x+t;
}
void add()
{
long long t;
al=al+l1;
t=al/mod;
al%=mod;
bl=bl+l2+t;
t=bl/mod;
bl%=mod;
cl=cl+l3+t;
}
void Minus()
{
long long t=0;
al=al-l1;
if(al<0)
{
al=al+mod;
bl-=1;
}
bl=bl-l2;
if(bl<0)
{
bl=bl+mod;
cl-=1;
}
cl=cl-l3;
}
void solve(long long n)
{
cl=bl=0;
al=1;
l1=n%mod;l2=n/mod;l3=0;
mul();
//cout<<l3<<' '<<l2<<' '<<l1<<endl;
muln(8);
//cout<<l3<<' '<<l2<<' '<<l1<<endl;
add();
//cout<<cl<<' '<<bl<<' '<<al<<endl;
l1=n%mod;l2=n/mod;l3=0;
//cout<<l3<<' '<<l2<<' '<<l1<<endl;
muln(7);
//cout<<l3<<' '<<l2<<' '<<l1<<endl;
Minus();
//cout<<cl<<' '<<bl<<' '<<al<<endl;
if(cl)
//cout<<cl<<' '<<bl<<' '<<al<<endl;
//printf("%I64d%09I64d%09I64d\n",cl,bl,al);
printf("%I64d%09I64d%09I64d\n",cl,bl,al);
else if(bl)
//cout<<bl<<' '<<al<<endl;
//printf("%I64d%09I64d\n",bl,al);
printf("%I64d%09I64d\n",bl,al);
else
cout<<al<<endl;
return;
}
int main()
{
int keng,ca=1;
scanf("%d",&keng);
long long n;
while(keng--)
{
//scanf("%I64d",&n);
cin>>n;
printf("Case #%d: ",ca++);
if(n==0)
cout<<1<<endl;
else
solve(n);
}
return 0;
}