ZOJ 3903 Ant ZOJ Monthly, October 2015 - A

Ant

Time Limit: 1 Second       Memory Limit: 32768 KB

There is an ant named Alice. Alice likes going hiking very much. Today, she wants to climb a cuboid. The length of cuboid's longest edge is n, and the other edges are all positive integers. Alice's starting point is a vertex of this cuboid, and she wants to arrive at the opposite vertex. The opposite vertex means the vertex which has no common planes or edges with the starting point. Just like the picture below:

mtz9548_ant_pic1.gif

Alice is very clever, she always walks on the shortest path. But she can only walk on the surface of the cuboid. Now, Alice only knows the length of cuboid's longest edge is n, and doesn't know the length of other edges. Suppose the L is the length of shortest path of a cuboid. Alice wants to compute the sum of L2 for every possible cuboid.

 

Input

The first line of input contains an integer T(T ≤ 100) . is the number of the cases. In the following T lines, there are a positive integer n(1≤n≤1014) in each line. n is the longest edge of the cuboid.

Output

For each test case, output the sum of L2 for every possible cuboid in a line. L is the length of shortest path of a cuboid. It may be very large, so you must output the answer modulo 1000000007.

Sample Input
2
3
4
Sample Output
160
440
Hint

(3,2,1) and (3,1,2) are regrad as the same cuboids.


Author: MU, Tongzhou

 

题意:就是说给出长方体的长(最长边),问一个蚂蚁从左下角爬到右后上角的所有可能的最短距离的和

解法:

1、听说有人用矩阵乘法过了,蛮厉害的,至今不知怎么推递推式

2、只能傻傻的推公示

显然一个蚂蚁有两种方式到达右后上角

设长为n,令两边为a,b,路程为c

c^2 = n^2+(a+b)^2 = n^2+a^2+b^2+2*a*b

或 c^2 = (n+a)^2+b^2 = n^2+a^2+b^2+2*a*n

显然是上面那个比较小

然后现有如下公式

A = 1+2+3+...+n = (n+1)*n/2

B = 1^2+2^2+3^2+.....+n^2 = n(n+1)(2n+1)/6

C = 1^3+2^3+3^3+......+n^3 = (n*(n+1)/2)^2

然后因为(n,a,b)跟(n,b,a)一样

不妨令a<b

那么(a,b)共有n*(n-1)/2种方式

所以   那个  n^2   总共的和为  n^2*n*(n-1)/2 = n^2*A

 

观察每种a^2、b^2被加的次数,发现

a^2 的总共的和为   1^2*n+2^2*(n-1)+......+n^2*1  =  sigma(1<=i<=n) i^2*(n-i+1) = sigma(1<=i<=n) (n+1)*i^2-i^3  

=   (n+1)*(1^2+2^2+3^2+.....+n^2)-(1^3+2^3+3^3+....+n^3)

= (n+1)*n(n+1)(2n+1)/6- (n*(n+1)/2)^2 = (n+1)*B-C

b^2 的总共的和为    1^2*1+2^2*2+.....+n^2*n =  (n*(n+1)/2)^2 = C

所以a^2+b^2= (n+1)*n(n+1)(2n+1)/6 = (n+1)*B

 

再观察2*a*b

就是 2*sigma(1<=i<=n) i*(i+(i+1)+.....+n)

= 2*sigma(1<=i<=n) i*(n+i)*(n-i+1)/2

= sigma(1<=i<=n)  i*(n^2-i^2+n+1)

= sigma(1<=i<=n)  n^2*i-i^3+n*i+i

= n^2*A-C+n*A+A

 

三者相加即可

(公式有可能打错,但思路没错,具体请看代码)

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <deque>
#include <queue>
using namespace std;
typedef long long LL;
typedef double DB;
#define Rep(i, n) for(int i = (0); i < (n); i++)
#define Repn(i, n) for(int i = (n)-1; i >= 0; i--)
#define For(i, s, t) for(int i = (s); i <= (t); i++)
#define Ford(i, t, s) for(int i = (t); i >= (s); i--)
#define rep(i, s, t) for(int i = (s); i < (t); i++)
#define repn(i, s, t) for(int i = (s)-1; i >= (t); i--)
#define MIT (2147483647)
#define MLL (1000000000000000000LL)
#define INF (1000000001)
#define mk make_pair
#define ft first
#define sd second
#define clr(x, y) (memset(x, y, sizeof(x)))
#define sqr(x) ((x)*(x))
#define sz(x) ((int) (x).size())
#define puf push_front
#define pub push_back
#define pof pop_front
#define pob pop_back
inline void SetIO(string Name) {
    string Input = Name+".in", Output = Name+".out";
    freopen(Input.c_str(), "r", stdin);
    freopen(Output.c_str(), "w", stdout);
}

const LL Mod = 1000000007LL;
const int Max = 20000010;
LL n;

inline LL GetLL() {
    LL Ret = 0;
    char Ch = ' ';
    while(!(Ch >= '0' && Ch <= '9')) Ch = getchar();
    while(Ch >= '0' && Ch <= '9') {
        Ret = Ret*10LL+Ch-'0';
        Ch = getchar();
    }
    return Ret;
}

inline void Solve();

inline void Input() {
    int TestNumber;
    scanf("%d", &TestNumber);
    while(TestNumber--) {
        n = GetLL();
        Solve();
    }
}

inline void Work(LL &m, bool &F2, bool &F3) {
    if(!F2 && m%2 == 0) F2 = 1, m /= 2;
    if(!F3 && m%3 == 0) F3 = 1, m /= 3;
    m %= Mod;
}

inline void Solve() {
    LL X, Y, Z;
    LL A, B, C;
    LL m;
    bool F2 = 0, F3 = 0;
    
    // Get X
    F2 = 0, F3 = 0, X = 1;
    m = n;
    Work(m, F2, F3);
    X = (X*m)%Mod;
    
    m = (n+1);
    Work(m, F2, F3);
    X = (X*m)%Mod;
    
    m = (2*n+1);
    Work(m, F2, F3);
    X = (X*m)%Mod;
    
    // Get Y
    F2 = 0, F3 = 1, Y = 1;
    m = n;
    Work(m, F2, F3);
    Y = (Y*m)%Mod;
    
    
    m = n+1;
    Work(m, F2, F3);
    Y = (Y*m)%Mod;
    
    Y = (Y*Y)%Mod;
    
    // Get Z
    F2 = 0, F3 = 1, Z = 1;
    m = n;
    Work(m, F2, F3);
    Z = (Z*m)%Mod;
    
    m = n+1;
    Work(m, F2, F3);
    Z = (Z*m)%Mod;
    
    m = n%Mod;
    // Get A
    A = Z;
    A = (A*m)%Mod;
    A = (A*m)%Mod;
    
    // Get B
    B = X;
    B = (B*(m+1))%Mod;
    
    // Get C
    C = (((m*m)%Mod)*Z)%Mod;
    C = (C-Y+Mod)%Mod;
    C = (C+X)%Mod;
    C = (C+((m*Z)%Mod))%Mod;
    
    LL Ans = (A+B+C)%Mod;
    cout<<Ans<<endl;
}

int main() {
     Input();
     //Solve();
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/StupidBoy/p/4883793.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值