0606算法竞赛_数学思想

题目:
0606算法竞赛_数学思想
题目分析:
假设共有n位,先考虑可重复,对于每一个数字x,它对总和做出的贡献为11…111(n个1)* (n - 1) ! * x

因此设sum = sigma ai * i

那么可重复的总和即为11…111(n个1)* (n - 1) ! * sum

那么对不可重复而言,我们只需除以每一个ai的排列之积即可

代码如下:

#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 << Sum << ' ' << part_I << ' '  << part_mul << ' ' << part_div << endl;
    cout << (LL)Sum * part_I %mod * part_mul %mod * part_div % mod << endl;
}

代码分析:
1.pow用平方的方式,快速求取余的次方
2.part_I记录n个1
3.part_mul记录count-1的阶乘
4.part_div记录每一个ai的排列之积的相反数(why?我们这里直接除可以吗?)

总结:
1.typedef long long LL写法
2.1e9+7写法

上一篇:SAP PM Permit (Part 1)


下一篇:vsto第一个例子