2020 Multi-University Training Contest 6 —— Road To The 3rd Building

Problem Description

在这里插入图片描述

Input

在这里插入图片描述

Output

在这里插入图片描述

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

Hint
The answer to the first testcase is 25/12.

num[1] num[2] num[3] num[4] num[5] … num[n - 1] num[n]
对于num[1] :num[1]共可以出现在num[1] / 1, num[1] / 2 … num[1] / n中
a[1]:num[1] * (inv[1] + inv[2] + inv[3] + … + inv[n])
a[2]:num[2] * [(inv[2] + inv[3] + … + inv[n]) + (inv[1] + inv[3] + … + inv[n - 1])]
a[3]:num[3] * [(inv[3] + inv[4] + … + inv[n]) + (inv[2] + inv[3] + … + inv[n-1]) + (inv[1] + inv[2] + … + inv[n - 3])]
a[4]:num[4] * [(inv[4] + inv[3] + … + inv[n]) + (inv[3] + inv[2] + … + inv[n-1]) + (inv[2] + inv[1] + … + inv[n - 3]) + (inv[1] + inv[2] + … + inv[n - 4)]
.
.
.
观察式子可以明显的发现对于a[k]有a[k] = a[k - 1] - (inv[1] + … + inv[k - 1]) + (inv[1] + inv[2] + … + inv[n - k])
其中我们可以通过线性求逆元的方法得到inv[ ]函数以及前缀和。
(期间我发现草稿纸上为了方便就一直没写inv符号,结果写代码的时候没用inv导致一直出错,还好没交。。)
分母部分就是(n +1)* n * inv[2].

代码如下:

//Siberian Squirrel
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define print(x) printf("%d\n", x)
typedef long long ll;
const double PI = acos(-1);
const int inf = 0x3f3f3f3f, MAXN = 2e6+10, MOD = 1000000007;
inline int read() {
    int res = 0;
    char c = getchar();
    while (!isdigit(c)) c = getchar();
    while (isdigit(c)) res = (res << 1) + (res << 3) + (c ^ 48), c = getchar();
    return res;
}
//
int T, n, a[MAXN], num[MAXN];
int res;
int fenzi, fenmu;
//
inline int quick_pow(int ans, int p, int mod, int res = 1) {
    for (; p; p >>= 1, ans = 1ll * ans * ans % mod)
        if (p & 1) res = 1ll * res * ans % mod;
    return res % mod;
}
inline int inv2(int res, int mod) {
    return quick_pow(res, mod - 2, mod) % MOD;
}
int inv[MAXN], qianzhui[MAXN];
inline void pre() {
    int n = 300000;
    inv[0] = inv[1] = 1;
    qianzhui[1] = 1;
    for (int i = 2; i <= n; ++i) {
        inv[i] = 1ll * (MOD - MOD / i) * inv[MOD % i] % MOD;
        qianzhui[i] = (qianzhui[i - 1] + inv[i]) % MOD;
    }
}
inline void get(int n) {
    a[1] = qianzhui[n] % MOD;
    for(int i = 2; i <= n; ++i) {
        a[i] = (1ll * qianzhui[n - i + 1] + a[i - 1] - qianzhui[i - 1] + MOD) % MOD;
    }
}
int main() {
    pre();
    T = read();
    while(T--) {
        res = 1;
        n = read(), fenzi = fenmu = 0;
        fenmu = 1ll * n * (n + 1) % MOD * 500000004 % MOD;
        res = 1ll * res * inv2(fenmu, MOD) % MOD;
        get(n);
        for(int i = 1; i <= n; ++i) {
            num[i] = read();
            fenzi = (fenzi + 1ll * num[i] * a[i] % MOD) % MOD;
        }
        res = 1ll * res * fenzi % MOD;
        printf("%d\n", (res + MOD) % MOD);
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值