解题思路:阶乘逆元+排列数
注意事项:用long long,每乘一个数就取模,避免溢出。

参考代码:

#include<bits/stdc++.h>


#define ll long long

using namespace std;


ll pow(ll a, int b, int mod) {

    ll res = 1;

    while (b) {

        if (b & 1) res = res * a % mod;

        a = a * a % mod;

        b >>= 1;

    }

    return res;

}


int counts[500001]{};

ll inv_fac[500001]{};

ll fac[500001]{};


int main() {

    ios::sync_with_stdio(false);

    cin.tie(nullptr);

    const int mod = 1e9 + 7;

    int n;

    cin >> n;

    int nums[n];

    for (int i = 0; i < n; i++) {

        int x;

        cin >> x;

        counts[x]++;

        nums[i] = x;

    }

    n -= 2;

    fac[0] = 1;

    for (int i = 1; i <= 500000; i++) fac[i] = fac[i - 1] * i % mod;

    inv_fac[500000] = pow(fac[500000], mod - 2, mod);

    for (int i = 499999; i >= 0; i--) inv_fac[i] = inv_fac[i + 1] * (i + 1) % mod;

    ll a = fac[n];

    for (int x:counts) if (x >= 2) a = a * inv_fac[x] % mod;

    ll ans = 0;

    for (int i = 1; i * i <= n; i++) {

        if (n % i != 0 || counts[i] == 0) continue;

        int j = n / i;

        if (counts[j] == 0 || i == j && counts[j] < 2) continue;

        if (i == j) ans = (ans + a * fac[counts[i]] % mod * inv_fac[counts[i] - 2] % mod) % mod;

        else

            ans = (ans + a * fac[counts[i]] % mod * fac[counts[j]] % mod * inv_fac[counts[i] - 1] % mod *

                         inv_fac[counts[j] - 1] % mod * 2 % mod) % mod;

    }

    cout << ans << endl;

    return 0;

}


点赞(0)
 

0.0分

0 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论