本文主要是介绍hdu 5047平面分割,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题目大意:
给n条样子像“m”的折线,求它们能把二维平面分成的面最多是多少。
解题思路:
我们发现直线1条:2平面;2直线:4平面;3直线:7平面......因为第n条直线要与前面n-1条直线都相交,才能使分的平面最多,则添加第n条直线,平面增加n个;
所以公式是面F = 2 + 2 + 3 + ......+ n = (1+n)*n/2 + 1
因为题目的是“M”的折线,一个“M”有4条线将平面分成2块,4条直线将平面分成11块,它们之间相差9块; 当两个“M”,平面分成19块,8条直线,平面分成37块,相差18,
是9的倍数。平面每增加一个“M”,平面的相当于增加4条直线,但要减去9块(结论在徒弟百度上面找到的,我也不知道为什么)。这个结论适合"z",“V”....这些折线都适合。
给n个“M”,公式F = (1+4*n)*4*n/2+1-n*9 = n*(8*n-7)+1
因为n最大是10^12,__int64(long long)都是9*10^18,n*n就会数据溢出。开始的时候没有计算时间复杂度,就用普通的大数运算,结果超时。后来师兄说大数有优化,
就是将一个大数分成左右两部分,分别用__int64 存。
因为防止两个数相乘数据溢出,所以我的数右半部分是9位数。举个例子 2100123456789,ans1=2100,ans0=123456789;
因为这个大数这样分,最多两部分所以推到公式如下
/************************ Author:fisty* DATA:2014-11-2* HDU5047* ******************/#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
#define MOD 1000000000
int main(){int t;scanf("%d", &t);for(int cnt = 1; cnt <= t; cnt++){ll n;scanf("%I64d", &n);printf("Case #%d: ", cnt);ll a[2],b[2],ans[2];a[0] = (8*n-7) % MOD;a[1] = (8*n-7) / MOD;b[0] = n % MOD;b[1] = n / MOD;ans[0] = (a[0]*b[0] + 1) % MOD;ans[1] = a[1]*b[1]*MOD + a[1]*b[0]+a[0]*b[1]+(a[0]*b[0]+1)/MOD;if(ans[1]){printf("%I64d%09I64d\n", ans[1], ans[0]);}else{printf("%I64d\n", ans[0]);}}return 0;
}
这篇关于hdu 5047平面分割的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!