HDU 5047 Sawtooth(大数模拟)上海赛区网赛1006

时间:2023-03-09 08:42:40
HDU 5047 Sawtooth(大数模拟)上海赛区网赛1006

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5047

解题报告:问一个“M”型可以把一个矩形的平面最多分割成多少块。

输入是有n个“M",现在已经推出这个公式应该是8 * n^2 - 7 * n + 1,但是这个n的范围达到了10^12次方,只要平方一次就超出long long  的范围了,怎么办呢,用大数?

都试过了,很奇怪,会超时,按照估算的话感觉不会,可能是中间结果比较大吧,这个还在思考,但是10^12平方一次乘以八也只达到了10^25次方级别,所以我们可以用四个__int64来模拟这个结果,这样计算起来就快多了。每一个只存结果的相应的八位,为什么只存八位呢,因为中间要进行平方运算,8位平方以下还好,在long long 的承受范围之内,如果大一点超过long long 就不行了,中间计算的时候相乘就容易溢出,而八位也刚好方便计算。相乘的时候要将大数的对应的位上的long long 两两进行相乘。

还有最后输出结果要注意一点,不能直接输出,中间的数前导0也要输出来,不然看起来就好像少了几个0,反正中间结果用8位的固定格式输出就行了。

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef __int64 INT;
struct Big
{
INT d[];
Big()
{
memset(d,,sizeof(d));
}
void print()
{
int flag = ;
for(int i = ;i >= ;--i)
if(d[i] != && !flag)
{
printf("%I64d",d[i]);
flag = ;
}
else if(flag) printf("%08I64d",d[i]);
puts("");
}
};
Big operator * (Big a,Big b)
{
Big c;
INT flag = ;
for(int i = ;i < ;++i)
for(int j = ;j < ;++j)
{
INT temp = a.d[i] * b.d[j] + flag;
if(temp) c.d[i+j] += temp % ;
flag = temp / ;
}
return c;
}
Big operator - (Big a,Big b)
{
Big c;
for(int i = ;i < ;++i)
{
if(a.d[i] < b.d[i])
{
a.d[i+] -= ;
a.d[i] += ;
}
c.d[i] = a.d[i] - b.d[i];
}
return c;
}
Big operator + (Big a,Big b)
{
Big c;
INT flag = ;
for(int i = ;i < ;++i)
{
INT temp = a.d[i] + b.d[i] + flag;
c.d[i] = temp % ;
flag = temp / ;
}
return c;
}
Big valueof(INT x)
{
int f = ;
Big ans;
while(x)
{
ans.d[f++] = x % ;
x /= ;
}
return ans;
}
int main()
{
int T,kase = ;
INT a;
scanf("%d",&T);
while(T--)
{
scanf("%I64d",&a);
Big ans = valueof(a) * valueof(a);
ans = ans * valueof();
ans = ans - (valueof(a) * valueof());
ans = ans + valueof();
printf("Case #%d: ",kase++);
ans.print();
}
return ;
}