• [Agc028B]Removing Blocks_排列组合


    Removing Blocks

    题目链接https://atcoder.jp/contests/agc028/tasks/agc028_b

    数据范围:略。


    题解

    这种问题的第一步很套路,就是对于每个$a_i$分开求。

    那么对于每个$a_i$应该怎么求呢?

    考虑删掉$j$的时候,有$a_i$贡献,有多少种方案。

    这样的话,需要保证$isim j$中间的所有数都被删掉了。

    考虑我们排列组合时候,广义来讲是先放谁都无所谓的。

    不妨先把那些应该在$j$后面出现的数先放进去,这样到了放$j$的时候就只有一种方案。

    方案数即为$frac{n!}{len_{(j ightarrow i)}}$。

    这个东西是$O(n^2)$的,用前缀和优化一下变成$O(n)$了。

    代码

    #include <bits/stdc++.h>
    
    #define N 300010 
    
    using namespace std;
    
    typedef long long ll;
    
    const int mod = 1000000007 ;
    
    char *p1, *p2, buf[100000];
    
    #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
    
    int rd() {
        int x = 0, f = 1;
        char c = nc();
        while (c < 48) {
            if (c == '-')
                f = -1;
            c = nc();
        }
        while (c > 47) {
            x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
        }
        return x * f;
    }
    
    int a[N], fac[N], fac2[N], bfr[N];
    
    int qpow(int x, int y) {
        int ans = 1;
        while (y) {
            if (y & 1) {
                ans = (ll)ans * x % mod;
            }
            y >>= 1;
            x = (ll)x * x % mod;
        }
        return ans;
    }
    
    int main() {
        int n = rd();
        for (int i = 1; i <= n; i ++ ) {
            a[i] = rd();
        }
    
        // init
        fac[0] = 1;
        for (int i = 1; i <= n; i ++ ) {
            fac[i] = (ll)fac[i - 1] * i % mod;
        }
        for (int i = 1; i <= n; i ++ ) {
            fac2[i] = (ll)fac[n] * qpow(i, mod - 2) % mod;
            bfr[i] = (bfr[i - 1] + fac2[i]) % mod;
        }
    
        // for (int i = 1; i <= n; i ++ ) {
        //     printf("%d ", fac[i]);
        // }
        // puts("");
        // for (int i = 1; i <= n; i ++ ) {
        //     printf("%d ", fac2[i]);
        // }
        // puts("");
    
        int ans = 0;
        for (int i = 1; i <= n; i ++ ) {
            ans = (ans + (ll)a[i] * (
                (((ll)bfr[i] + bfr[n - i + 1]) % mod + mod - fac[n]) % mod
            )) % mod;
        }
    
        cout << ans << endl ;
        return 0;
    }
    
  • 相关阅读:
    Stream 和 byte[] 之间的转换
    C# Process类_进程_应用程序域与上下文之间的关系
    C# Process类_进程管理器Demo
    C# attribute_特性
    SqlDataAdapter类
    SqlDataReader类
    SqlCommand类
    SqlConnection类
    DataTable类
    C# 语法技巧_三目运算_switch_case
  • 原文地址:https://www.cnblogs.com/ShuraK/p/11738457.html
Copyright © 2020-2023  润新知