传送
题意:
题解:
我们来考虑以下样例:1,1,2
我们先考虑1的贡献:如图(图中只花了)
2!表示还剩两个空位,还有两个数未填入,所以是2!个
对于n个数重复,考虑重复的情况就是:111…11(一共n个)* (n-1)! * sum
sum为Σa[i] * i,即每个数出现的次数 *这个数的总和
然后考虑去重:
1,1,2所组成的重复情况有:
112,112
其中我用()括号来将1分号
1(1)1(2)2,1(2)1(1)2
也就是虽然这两个的1是不同贡献的,但是最终组成结果一样,所以要去掉,怎么去?在这个例子中除以2,因为有两个1重复了。那我们现在用1,1,1,2组成重复情况有:1112,1112,1112,1112,1112,1112,会发现有6个重复情况,因为三个1全排列有6种情况,所以我们除以6,也就是重复x次,就除以x!,注意除了1重复,2也有可能,所以每个数都要去除重复,我们设a[i]表示第i个数出现的次数所以就要除以(a[1]!*a[2]!..a[9]!)
总结答案就是:
ans=(11…111(一共n个1)) * (n-1) * sum/(a[1]!*a[2]!..a[9]!)
答案要取模
代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e6 + 5;
const int mod = 1e9 + 7;
int fac[N], ifac[N];
int T[20];
typedef long long LL;int pow(int a, int b) {LL res = 1;for(;b;b >>= 1, a = (LL) a * a % mod) if (b & 1) res = res * a % mod;return res;
}int main() {int Max = 1000000;fac[0] = 1;for(int i = 1; i <= Max; ++ i) fac[i] = (LL)fac[i - 1] * i % mod;ifac[Max] = pow(fac[Max], mod - 2);for(int i = Max-1; i >= 0; -- i) ifac[i] = (LL)ifac[i + 1] * (i + 1) % mod;LL Sum = 0;int Count = 0;for(int i = 1; i <= 9; ++ i) {int temp;cin >> temp;T[i] = temp;Sum += i * temp;Count += T[i];} Sum %= mod;LL part_I = 0;for(int i = 1; i <= Count; ++ i) part_I = (part_I * 10 + 1) % mod;LL part_mul = fac[Count - 1];LL part_div = 1;for(int i = 1; i<= 9; ++ i) part_div = part_div * ifac[T[i]] % mod;cout << (LL)Sum * part_I %mod * part_mul %mod * part_div % mod << endl;
}