HDUOJ 6827 Road To The 3rd Building
Problem Description
Because of the thriller adventure game The 3rd Building, there are fewer and fewer students who would like to go to the 3rd Building. So few students are working in the studio in the 3rd Building. Students are even more reluctant to go to the 3rd Building for experiments, which are also annoying.
Kanade takes responsibility to improve this status. She thinks it a good idea to decorate the ginkgo trees along the road to the 3rd Building, making them cute. There are n ginkgo trees that are planted along the road, numbered with 1…n. Each tree has a cute value. The cute value of tree i is si.
Kanade defines a plan as an ordered pair (i,j), here 1≤i≤j≤n. It means a student will appear at the position of the tree i magically, walk along the road, and finally stop walking at the position of the tree j. The cute level of a plan is the average of the cute value of the trees visited. Formally, the cute level of plan (i,j) is 1 j − i + 1 ∑ k = i j s k \frac{1}{j−i+1}\sum^j_{k=i}s_k j−i+11∑k=ijsk.
Kanade wants to know the mathematical expectation of the cute level if a student will take a plan among all these plans in a uniformly random way. But she is busy with learning Computer Networking, would you help her?
Input
The first line of the input contains an integer T — the number of testcases. You should process these testcases independently.
The first line of each testcase contains an integer n — the number of ginkgo trees.
The second line of each testcase contains n integers si — the cute value of each ginkgo tree, space-separated.
1≤T≤20,1≤n≤2×105,1≤si≤1e9
It is guaranteed that ∑n≤1e6.
Output
For each testcase, output the answer in the fraction form modulo 109+7 in one line. That is, if the answer is PQ, you should output P⋅Q−1mod(1e9+7), where Q−1 denotes the multiplicative inverse of Q modulo 1e9+7.
Sample Input
3
3
1 3 2
6
1 1 4 5 1 4
9
7325 516 56940 120670 16272 15007 337527 333184 742294
Sample Output
83333336
188888893
303405448
简单数论题~
首先可以求出总情况是
n
∗
(
n
+
1
)
2
\frac{n*(n+1)}{2}
2n∗(n+1)
然后对每一个
i
∈
[
1
,
n
∗
(
n
+
1
)
2
]
i\in[1,\frac{n*(n+1)}{2}]
i∈[1,2n∗(n+1)] 做考虑,每一个分母很简单,就是
1
i
\frac{1}{i}
i1,下面来看分子的规律:
拿
n
=
6
n=6
n=6 举例:
- i = 1 i=1 i=1,分子为 a [ 1 ] + a [ 2 ] + a [ 3 ] + a [ 4 ] + a [ 5 ] + a [ 6 ] a[1]+a[2]+a[3]+a[4]+a[5]+a[6] a[1]+a[2]+a[3]+a[4]+a[5]+a[6]
- i = 2 i=2 i=2,分子为 a [ 1 ] + 2 ∗ a [ 2 ] + 2 ∗ a [ 3 ] + 2 ∗ a [ 4 ] + 2 ∗ a [ 5 ] + a [ 6 ] a[1]+2*a[2]+2*a[3]+2*a[4]+2*a[5]+a[6] a[1]+2∗a[2]+2∗a[3]+2∗a[4]+2∗a[5]+a[6]
- i = 3 i=3 i=3,分子为 a [ 1 ] + 2 ∗ a [ 2 ] + 3 ∗ a [ 3 ] + 3 ∗ a [ 4 ] + 2 ∗ a [ 5 ] + a [ 6 ] a[1]+2*a[2]+3*a[3]+3*a[4]+2*a[5]+a[6] a[1]+2∗a[2]+3∗a[3]+3∗a[4]+2∗a[5]+a[6]
- i = 4 i=4 i=4,分子为 a [ 1 ] + 2 ∗ a [ 2 ] + 3 ∗ a [ 3 ] + 3 ∗ a [ 4 ] + 2 ∗ a [ 5 ] + a [ 6 ] a[1]+2*a[2]+3*a[3]+3*a[4]+2*a[5]+a[6] a[1]+2∗a[2]+3∗a[3]+3∗a[4]+2∗a[5]+a[6]
- i = 5 i=5 i=5,分子为 a [ 1 ] + 2 ∗ a [ 2 ] + 2 ∗ a [ 3 ] + 2 ∗ a [ 4 ] + 2 ∗ a [ 5 ] + a [ 6 ] a[1]+2*a[2]+2*a[3]+2*a[4]+2*a[5]+a[6] a[1]+2∗a[2]+2∗a[3]+2∗a[4]+2∗a[5]+a[6]
- i = 6 i=6 i=6,分子为 a [ 1 ] + a [ 2 ] + a [ 3 ] + a [ 4 ] + a [ 5 ] + a [ 6 ] a[1]+a[2]+a[3]+a[4]+a[5]+a[6] a[1]+a[2]+a[3]+a[4]+a[5]+a[6]
不难发现系数是有规律的,我们预处理出前缀和
s
u
m
sum
sum,那么可以处理出分子
s
s
s:
s
[
i
+
1
]
=
s
[
i
]
+
s
u
m
[
n
−
i
]
−
s
u
m
[
i
]
,
i
∈
[
0
,
n
)
s[i+1]=s[i]+sum[n-i]-sum[i],i\in[0,n)
s[i+1]=s[i]+sum[n−i]−sum[i],i∈[0,n)
那么答案就是:
a
n
s
=
∑
i
=
1
n
s
[
i
]
i
n
∗
(
n
+
1
)
2
ans=\frac{\sum_{i=1}^n\frac{s[i]}{i}}{\frac{n*(n+1)}{2}}
ans=2n∗(n+1)∑i=1nis[i]
AC代码如下,有两个小细节我都在代码里注释了:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
const ll mod=1e9+7;
ll t,n,inv[N],s[N],sum[N],a[N];
ll power(ll a,ll b){return b?power(a*a%mod,b/2)*(b%2?a:1)%mod:1;}
void init(){
for(ll i=1;i<N;i++) inv[i]=power(i,mod-2);
}
int main(){
init();
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
memset(s,0,sizeof(s));
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sum[i]=(a[i]%mod+sum[i-1])%mod;
ll ans=0;
for(int i=0;i<(n+1)/2;i++){
s[i+1]=(s[i]+sum[n-i]-sum[i]+mod)%mod;//注意负数
if((i+1)!=n-i) ans=(ans+s[i+1]*((inv[i+1]+inv[n-i])%mod)%mod)%mod;
else ans=(ans+s[i+1]*inv[i+1]%mod)%mod;
}
printf("%lld\n",ans*power(n*(n+1)/2%mod,mod-2)%mod);//底数取模防爆
}
return 0;
}