转自http://blog.csdn.net/bigbigship/article/details/49123643
题意:
告诉你一个长方体的最长边,从任意一个顶点走到与其不在长方体同一个表面上的顶点求这个最短距离 ΣL2 。
分析:
- 公式推导
设最长的边为 n ,最短的边为 x ,次短的边为 y ,
ΣL2=∑nx=1∑ny=xn2+(x+y)2
ΣL2=n∗(n+1)/2∗n2+∑nx=1∑ny=xx2+y2+2∗x∗y
设 Sum1=∑nx=1∑ny=x2∗x∗y
Sum1=∑nx=12∗x∑ny=xy
Sum1=∑nx=12∗x∗(x+n)∗(n−x+1)/2
Sum1=∑nx=1−x3+x2+(n2+n)∗x
设 Sum2=∑nx=1∑ny=xx2+y2 由于 x,y 的取值范围都为 [1,n] ,并且每个数的平方都恰好出现了 n+1 次
因此 Sum2=∑nx=1x2∗(n+1)
ΣL2=Sum1+Sum2=∑nx=1−x3+(n+2)∗x2+(n2+n)∗x - 补充三个求和公式:
∑nx=1x=n∗(n+1)/2
∑nx=1x2=n∗(n+1)∗(2∗n+1)/6
∑nx=1x3=[n∗(n+1)/2]2
我的代码两种形式求除法逆元
扩展欧几里德:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
ll r = exgcd(b, a % b, x, y);
ll t = x % mod;
x = y % mod;
y = ((t - a / b * y) % mod + mod) % mod;
return r;
}
int main()
{
ll x, y;
ll inv2, inv4, inv6;
exgcd(2, mod, inv2, y);
exgcd(4, mod, inv4, y);
exgcd(6, mod, inv6, y);
ll T, n;
printf("%lld, %lld, %lld\n", inv2, inv4, inv6);
scanf("%lld", &T);
while (T--)
{
scanf("%lld", &n);
n %= mod;
ll ans = (n * n % mod + n) % mod * n % mod * n % mod * inv2 % mod;
ans += ((n * (n + 1) % mod) * n % mod * (n + 1) % mod * inv2 % mod) % mod;
ans += (n + 2) * n % mod * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod;
ans =(((ans - n * n % mod * (n + 1) % mod * (n + 1) % mod * inv4 % mod + mod) % mod + mod) % mod);
printf("%lld\n", ans);
}
return 0;
}
费马小定理:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
ll r = exgcd(b, a % b, x, y);
ll t = x % mod;
x = y % mod;
y = ((t - a / b * y) % mod + mod) % mod;
return r;
}
int main()
{
ll x, y;
ll inv2, inv4, inv6;
exgcd(2, mod, inv2, y);
exgcd(4, mod, inv4, y);
exgcd(6, mod, inv6, y);
ll T, n;
printf("%lld, %lld, %lld\n", inv2, inv4, inv6);
scanf("%lld", &T);
while (T--)
{
scanf("%lld", &n);
n %= mod;
ll ans = (n * n % mod + n) % mod * n % mod * n % mod * inv2 % mod;
ans += ((n * (n + 1) % mod) * n % mod * (n + 1) % mod * inv2 % mod) % mod;
ans += (n + 2) * n % mod * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod;
ans =(((ans - n * n % mod * (n + 1) % mod * (n + 1) % mod * inv4 % mod + mod) % mod + mod) % mod);
printf("%lld\n", ans);
}
return 0;
}