zoukankan      html  css  js  c++  java
  • 【计数】cf938E. Max History

    发现有一种奇怪的方法不能快速预处理?

    复习一下常见的凑组合数的套路

    You are given an array a of length n. We define fa the following way:

    • Initially fa = 0, M = 1;
    • for every 2 ≤ i ≤ n if aM < ai then we set fa = fa + aM and then set M = i.

    Calculate the sum of fa over all n! permutations of the array a modulo 109 + 7.

    Note: two elements are considered different if their indices differ, so for every array a there are exactly n! permutations.

    Input

    The first line contains integer n (1 ≤ n ≤  1 000 000) — the size of array a.

    Second line contains n integers a1, a2, ..., an (1 ≤  ai ≤  109).

    Output

    Print the only integer, the sum of fa over all n! permutations of the array a modulo 109 + 7.


    题目大意

    题目分析

    主要是记一下一种凑组合数的常见套路,网上其他人都是一种另外的考虑方式。

    对于数$a_q$枚举它每一个出现位置的贡献,记严格小于它的数有$m$个,则有$a_qsumlimits_{p=1}^n{m choose {p-1}}(p-1)! (n-p)!$即$a_q m!sumlimits_{p=1}^n{{(n-p)!}over {(m-p+1)!}}$。于是就会发现右边这个东西分子分母都有自变量,看上去很难处理,但形式上又是有些相似的感觉。

    式子可以接着这么化:$a_qm!(n-m+1)!sumlimits_{p=1}^n{{n-p}choose{n-m-1}}$,也就是把右式做成一个组合数。

    注意到新的右式是经典问题组合数的列前缀和,于是化成:$a_qm!(n-m+1)!{{n}choose{n-m}}$

    最后化简得到:$a_qn!over{n-m}$

     1 #include<bits/stdc++.h>
     2 #define MO 1000000007
     3 const int maxn = 1000035;
     4 
     5 int n,ans,cnt,a[maxn],fac[maxn],inv[maxn];
     6 
     7 int read()
     8 {
     9     char ch = getchar();
    10     int num = 0, fl = 1;
    11     for (; !isdigit(ch); ch=getchar())
    12         if (ch=='-') fl = -1;
    13     for (; isdigit(ch); ch=getchar())
    14         num = (num<<1)+(num<<3)+ch-48;
    15     return num*fl;
    16 }
    17 int main()
    18 {
    19     n = read();
    20     for (int i=1; i<=n; i++) a[i] = read();
    21     std::sort(a+1, a+n+1);
    22     fac[0] = fac[1] = inv[0] = inv[1] = 1;
    23     for (int i=2; i<=n+2; i++)
    24         inv[i] = MO-1ll*(MO/i)*inv[MO%i]%MO, 
    25         fac[i] = 1ll*fac[i-1]*i%MO;
    26     for (int i=1,j; i<=n; i=j+1)
    27     {
    28         for (j=i; a[j+1]==a[i]; j++);
    29         if (j==n) break;
    30         cnt = inv[n-i+1];
    31         ans = (1ll*ans+1ll*a[i]*(j-i+1)%MO*cnt%MO)%MO;
    32     }
    33     printf("%d
    ",1ll*ans*fac[n]%MO);
    34     return 0;
    35 }

    END 

  • 相关阅读:
    可由inetd启动的协议无关时间获取服务器程序
    daemon_inetd函数
    作为守护进程运行的协议无关时间获取服务器程序
    daemon_init函数:调用该函数把普通进程转变为守护进程
    getnameinfo函数
    tcp_connect函数
    20200311 11. 应用生命周期事件
    20200311 10. Web 应用
    20200311 9. 分派请求
    20200311 8. 注解和可插拔性
  • 原文地址:https://www.cnblogs.com/antiquality/p/10573199.html
Copyright © 2011-2022 走看看