分析:数学题、大整数。地推求公式,然后大整数模拟。
如图,n为1、2、3的情况为上面的小圆,下面的大圆为在n-1的情况下,加入第n个点的状态;
1.计算增量:
图中取第n个点与第i个点连接的状态,这条线将点分成2个集合(除去i和n):【1,i-1】,【i+1,n-1】;
这两个集合中的任意两点连线都会与i-n相交,各自内部的点都不会与i-n相交,共(i-1)*(n-1-i)个交点;
存在k个交点,则分i-n为k+1段,这k+1段线段将各自经过的区域一分为2,所以增加了k+1个区域;
下面,求n与所有顶点连线后增加的区域总数:f(n)= Σ【(i-1)*(n-1-i)+ 1】,i 取值【1,n-1】;
看着有点复杂,不过Σi*(n-i+1)= n*(n+1)*(n+2)/ 6,可以用数学归纳法证明;
因此:f(n)= (n-1)*(n^2 - 5n + 12)/ 6,这个公式对于n≥2都成立,其中f(1)= 0,也认为成立;
2.计算总数:
不过 f(n)是增量的公式,我们要的结果是:g(n)= g(1)+ Σ f(i),i 取值【1,n】,g(1)= 1;
将g(n)的公式展开成0次、1次、2次、3次的和式,然后利用各自的求和公式计算,整理得到结果:
g(n)= 1 - 2n + (30 -7n + n^2)* n*(n+1)/ 24;
数据范围很大,使用long long数组模拟计算防止溢出;
说明:这里有个坑,n = 2^31-1时+1后会溢出,所以需要将n转化成long long类型再计算。
#include <cstdlib>
#include <cstdio>
#define out_format(s1,w,s2) #s1#w#s2
const int big_max_size = 10; // length
const long long big_base = 100000000LL; // base
const char *big_print_format = "%08lld"; // width
long long ans[big_max_size+1];
long long buf[big_max_size+1];
void big_zero(long long a[])
{
for (int i = 0; i < big_max_size; ++ i) {
a[i] = 0;
}
}
void big_one(long long a[])
{
big_zero(a);
a[0] = 1LL;
}
void big_carry(long long a[])
{
for (int i = 0; i < big_max_size; ++ i) {
if (a[i] >= big_base) {
a[i+1] += a[i]/big_base;
a[i] %= big_base;
}
}
}
void big_add(long long a[], long long b[]) // a = a + b
{
for (int i = 0; i < big_max_size; ++ i) {
a[i] += b[i];
}
big_carry(a);
}
void big_sub(long long a[], long long b[]) // a = a - b
{
for (int i = 0; i < big_max_size; ++ i) {
a[i] -= b[i];
if (a[i] < 0LL) {
a[i+1] -= 1;
a[i] += big_base;
}
}
big_carry(a);
}
void big_mul(long long a[], long long value) // a = a * b
{
for (int i = 0; i < big_max_size; ++ i) {
a[i] *= value;
}
big_carry(a);
}
void big_div(long long a[], long long value) // a = a / b
{
for (int i = big_max_size-1; i > 0; -- i) {
a[i-1] += a[i]%value*big_base;
a[i] /= value;
}
a[0] /= value; // if (a[0]%value != 0) there is something wrong
}
void big_print(long long a[])
{
int end = big_max_size-1;
while (!a[end] && end > 0) {
-- end;
}
printf("%lld",a[end --]);
while (end >= 0) {
printf(big_print_format,a[end --]);
} // if big_base != 10 should change the format
puts("");
}
int main()
{
int s, n;
while (~scanf("%d",&s)) {
for (int i = 0; i < s; ++ i) {
scanf("%d",&n);
big_one(ans); // n*n*n*(n+1)
big_mul(ans, n);
big_mul(ans, n);
big_mul(ans, n);
big_mul(ans, n+1LL);
big_one(buf); // 7*n*n*(n+1)
big_mul(buf, 7);
big_mul(buf, n);
big_mul(buf, n);
big_mul(buf, n+1LL);
big_sub(ans, buf);
big_one(buf); // 30*n*(n+1)
big_mul(buf, 30);
big_mul(buf, n);
big_mul(buf, n+1LL);
big_add(ans, buf);
big_div(ans, 24);
big_one(buf); // 2n
big_mul(buf, 2);
big_mul(buf, n);
big_sub(ans, buf);
big_one(buf); // 1
big_add(ans, buf);
big_print(ans);
}
}
return 0;
}