黑暗爆炸 - 3028 食物 - 生成函数 + 母函数

传送门

挺有意思的模板题。
记住几个基本的生成函数

对于\(1+x^k+x^{2k} + \dots = \frac{1}{1 - x^k}\)
\(x + x^{k+1} + x^{2k+1} + \dots = \frac{x}{1-x^k}\)

那么把所有的式子变成母函数后再相乘,就有\(\frac{x}{(1-x)^4}\)

那么答案就是\(x(1+x+x^2+\dots + )^4\)

等价于任意取4个价值不同的,然后再取一个价值为1的,最后组合一下,和是\(n\)的种类数

根据非负整数解的个数公式
\(n\)个物品放进\(k\)个盒子里的方法总数为\(\begin{equation} \left(\begin{array}{l} n+k - 1 \\ k-1 \end{array}\right) \end{equation}\)(允许有空盒子)

那么答案就是\(C_{n+2}^3\),用大整数去做就行了

#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define CASE int Kase = 0; cin >> Kase; for(int kase = 1; kase <= Kase; kase++)
using namespace std;
template<typename T = long long> inline T read() {
    T s = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    while(isdigit(ch)) {s = (s << 3) + (s << 1) + ch - 48; ch = getchar();} 
    return s * f;
}
#ifdef ONLINE_JUDGE
#define qaq(...) ;
#else
template <typename... T> void qaq(const T &...args) {
    auto &os = std::cerr;
    (void)(int[]){(os << args << " ", 0)...};
    os << std::endl;
}
#endif
const int N = 1e5 + 5, MAXN = 1e4 + 5, MOD = 1e9 + 7, CM = 998244353, INF = 0x3f3f3f3f; const ll linf = 0x7f7f7f7f7f7f7f7f;
struct BigInteget{ // 非负整数范围运行
    int digit[MAXN];
    int length;
    BigInteget();
    BigInteget(int x);
    BigInteget(string str);
    BigInteget(const BigInteget& b);
    BigInteget operator =(int x);
    BigInteget operator =(string str);
    BigInteget operator =(const BigInteget& b);
    bool operator <=(const BigInteget& b);
    bool operator ==(const BigInteget& b);
    bool operator >(const BigInteget& b);
    BigInteget operator +(const BigInteget& b);
    BigInteget operator -(const BigInteget& b);
    BigInteget operator *(const BigInteget& b);
    BigInteget operator /(const BigInteget& b);
    BigInteget operator %(const BigInteget& b);
    friend istream& operator>>(istream& in, BigInteget& x);
    friend ostream& operator<<(ostream& out, const BigInteget& x);
    void show();
};
istream& operator >> (istream& in, BigInteget& x){
    string str;
    in >> str;
    x = str;
    return in;
}
ostream& operator << (ostream& out, const BigInteget& x){
    for(int i = x.length-1; i >= 0; i--)
        out << x.digit[i];
    return out;
}
BigInteget::BigInteget(){
    memset(digit, 0, sizeof(digit));
    length = 0;
}
BigInteget::BigInteget(int x){
    memset(digit, 0, sizeof(digit));
    length = 0;
    if(x == 0)
        digit[length++] = x;
    while(x) {
        digit[length++] = x % 10;
        x /= 10;
    }
}
BigInteget::BigInteget(string str){
    memset(digit, 0, sizeof(digit));
    length = str.size();
    for(int i = 0; i < length; i++)
        digit[i] = str[length - i - 1] - '0';
}
BigInteget::BigInteget(const BigInteget& b){
    memset(digit, 0, sizeof(digit));
    length = b.length;
    for(int i = 0; i < length; i++)
        digit[i] = b.digit[i];
}
BigInteget BigInteget::operator = (int x){
    memset(digit, 0, sizeof(digit));
    length = 0;
    if(x == 0)
        digit[length++] = x;
    while(x){
        digit[length++] = x % 10;
        x /= 10;
    }
    return *this;
}
BigInteget BigInteget::operator = (string str){
    memset(digit, 0, sizeof(digit));
    length = str.size();
    for(int i = 0; i < length; i++)
        digit[i] = str[length - i - 1] - '0';
    return *this;
}
BigInteget BigInteget::operator = (const BigInteget& b){
    memset(digit, 0, sizeof(digit));
    length = b.length;
    for(int i = 0; i < length; i++)
        digit[i] = b.digit[i];
    return *this;
}
bool BigInteget::operator > (const BigInteget &b) {
    if(length > b.length) return true;
    else if(b.length > length) return false;
    else {
        for(int i = length - 1; i >= 0; i--) {
            if(digit[i] == b.digit[i]) continue;
            else return digit[i] > b.digit[i];
        }
    }
    return false;
}
bool BigInteget::operator <= (const BigInteget& b) {
    if(length < b.length) return true;
    else if (b.length < length) return false;
    else {
        for(int i = length - 1; i >= 0; i--) {
            if(digit[i] == b.digit[i]) continue;
            else return digit[i] < b.digit[i];
        }
    }
    return true;
}

bool BigInteget::operator == (const BigInteget& b){
    if(length != b.length) return false;
    else{
        for(int i = length -1; i >= 0; i--){
            if(digit[i] != b.digit[i])
                return false;
        }
    }
    return true;
}
BigInteget BigInteget::operator + (const BigInteget& b){
    BigInteget answer;
    int carry = 0;
    for(int i = 0; i < length || i < b.length; i++){
        int current = carry + digit[i] + b.digit[i];
        carry = current /10;
        answer.digit[answer.length++] = current % 10;
    }
    if(carry){
        answer.digit[answer.length++] = carry;
    }
    return answer;
}
BigInteget BigInteget::operator - (const BigInteget& b){
    BigInteget answer;
    int carry = 0;
    for(int i = 0; i < length; i++){
        int current = digit[i] - b.digit[i] - carry;
        if(current < 0) {
            current += 10;
            carry = 1;
        } else carry  = 0;
        answer.digit[answer.length++] = current;
    }
    while(answer.digit[answer.length - 1] == 0 && answer.length > 1){//书上在这里写得是answer.digit[answer.length]
        answer.length--;
    }
    return answer;
}
BigInteget BigInteget::operator * (const BigInteget& b){
    BigInteget answer;
    answer.length = length + b.length;
    for(int i = 0; i < length; i++){
        for(int j = 0; j < b.length; j++)
            answer.digit[i+j] += digit[i] * b.digit[j];
    }
    for(int i = 0; i < answer.length; i++){
        answer.digit[i+1] += answer.digit[i] / 10;
        answer.digit[i] %= 10;
    }
    while(answer.digit[answer.length - 1] == 0 && answer.length > 1){ //书上在这里写得是answer.digit[answer.length]
        answer.length--;
    }
    return answer;
}

BigInteget BigInteget::operator / (const BigInteget& b){
    BigInteget answer;
    answer.length = length;
    BigInteget remainder = 0;
    BigInteget temp = b;
    for(int i = length - 1; i >= 0; i--){
        if(!(remainder.length == 1 && remainder.digit[0] == 0)){
            for(int j = remainder.length -1; j >= 0; j--)
                remainder.digit[j + 1] = remainder.digit[j];
            remainder.length++;
        }
        remainder.digit[0] = digit[i];
        while(temp <= remainder){
            remainder = remainder - temp;
            answer.digit[i]++;
        }
    }
    while(answer.digit[answer.length - 1] == 0 && answer.length > 1){//书上在这里写得是answer.digit[answer.length]
        answer.length--;
    }
    return answer;
}
BigInteget BigInteget::operator % (const BigInteget &b){
    BigInteget remainder = 0;
    BigInteget temp = b;
    for(int i = length - 1; i >= 0; i--) {
        if(!(remainder.length == 1 && remainder.digit[0] == 0)){
            for(int j = remainder.length - 1; j >= 0; j--)
                remainder.digit[j + 1] = remainder.digit[j];
            remainder.length++;
        }
        remainder.digit[0] = digit[i];
        while(temp <= remainder){
            remainder = remainder - temp;
        }
    }
    return remainder;
}
void BigInteget::show() {
    for(int i = length - 1; i >= 0; i--)
        printf("%d", digit[i]);
    putchar('\n');
}
void solve(int kase){
    BigInteget mod = 10007;
    BigInteget n;
    cin >> n;
    cout << n * (n + 1) * (n + 2) / 6 % mod << endl;
}
const bool ISFILE = 0, DUO = 0;
int main(){
    clock_t start, finish; double totaltime; start = clock();
    if(ISFILE) freopen("/Users/i/Desktop/practice/in.txt", "r", stdin);
    if(DUO) {CASE solve(kase);} else solve(1);
    finish = clock(); 
    #ifdef ONLINE_JUDGE
        return 0;
    #endif
    printf("\nTime: %lfms\n", (double)(finish - start) / CLOCKS_PER_SEC * 1000);
    return 0;
}
posted @ 2021-02-24 14:46  Emcikem  阅读(63)  评论(0编辑  收藏  举报