Codechef CNTL Counting is life 生成函数

传送门——Vjudge


第一问很氵,如果\(K,N\)同奇偶就是\(2^K-1\),否则就是\(2^K-2\)

第二问似乎是可重排列,考虑指数型生成函数。

如何限制某些数必须要出现奇数/偶数次?考虑\(\frac{e^x-e^{-x}}{2}\),可以发现它的展开式中只有次数为奇数的项有值,而\(\frac{e^x+e^{-x}}{2}\)只有次数为偶数的项有值。

于是当\(K,N\)同奇偶时答案是\(N!(\frac{e^x-e^{-x}}{2})^K\),否则是\(N!(\frac{e^x-e^{-x}}{2})^{K-1}\frac{e^x+e^{-x}}{2}\)

暴力二项式定理拆开\((\frac{e^x - e^{-x}}{2})^K\)就可以算了。

#include<iostream>
#include<cstdio>
//This code is written by Itst
using namespace std;

inline int read(){
    int a = 0;
    char c = getchar();
    while(!isdigit(c))
        c = getchar();
    while(isdigit(c)){
        a = a * 10 + c - 48;
        c = getchar();
    }
    return a;
}

const int MOD = 1e9 + 7;
inline int poww(long long a , int b){
    int times = 1;
    a = (a + MOD) % MOD;
    while(b){
        if(b & 1) times = times * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return times;
}

const int MAXN = 1e5 + 7;
int T , N , K , jc[MAXN] , inv[MAXN];

void init(){
    jc[0] = 1;
    for(int i = 1 ; i <= 1e5 ; ++i)
        jc[i] = 1ll * jc[i - 1] * i % MOD;
    inv[100000] = poww(jc[100000] , MOD - 2);
    for(int i = 1e5 - 1 ; i >= 0 ; --i)
        inv[i] = inv[i + 1] * (1ll + i) % MOD;
}

int binom(int b , int a){
    return b < a ? 0 : 1ll * jc[b] * inv[a] % MOD * inv[b - a] % MOD;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    //freopen("out","w",stdout);
#endif
    init();
    for(T = read() ; T ; --T){
        N = read(); K = read();
        if((N ^ K) & 1){
            cout << poww(2 , K) - 2 << ' ';
            int ans = 0;
            for(int i = 0 ; i < K ; ++i)
                ans = (ans + (i & 1 ? -1ll : 1ll) * binom(K - 1 , i) * (poww(K - 1 - 2 * i + 1 , N) + poww(K - 1 - 2 * i - 1 , N)) % MOD + MOD) % MOD;
            cout << 1ll * ans * poww(poww(2 , K) , MOD - 2) % MOD << '\n';
        }
        else{
            cout << poww(2 , K) - 1 << ' ';
            int ans = 0;
            for(int i = 0 ; i <= K ; ++i)
                ans = (ans + (i & 1 ? -1ll : 1ll) * binom(K , i) * poww(K - 2 * i , N) % MOD + MOD) % MOD;
            cout << 1ll * ans * poww(poww(2 , K) , MOD - 2) % MOD << '\n';
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/Itst/p/10548722.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值