hdu 5047 Sawtooth 2014 ACM/ICPC Asia Regional Shanghai Online 数学

题目链接: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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值