• [题解] [Codechef] CNTL


    题面

    题解

    第一问很简单, 如果 (n - k) 是偶数那么答案就是 (2 ^ k - 1) , 如果 (n - k) 是奇数答案就是 (2^k - 2)

    第二问怎么办, 我们对于 (n - k) 是偶数讨论

    我们要做的是, 对于每一个数, 我们要让他选奇数次最后的答案可能性才会最大

    并且所有的数选的次数加起来是 (n)

    我们考虑指数型生成函数 (frac{e^x-e^{-x}}{2})

    把它展开后, 偶数位都是 (0) , 奇数位都是 (1)

    那么我们只要求 (frac{e^x-e^{-x}}{2}^k)(x ^ n) 上的系数即可

    如果 (n - k) 是奇数的话就变成求 (frac{e^x-e^{-x}}{2}^{k-1}*frac{e^x+e^{-x}}{2})(x^n) 上的系数, 即 (1) 取偶数个, 其他的都取奇数个

    二项式定理展开即可

    注意最后答案还要乘上一个 (n!) 因为我们算出来的是无序方案, 但答案事实上是求有序方案

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    const int N = 100005;
    const int mod = 1e9 + 7; 
    using namespace std;
    
    int T, n, k, fac[N], inv[N], pow[N], ans; 
    
    template < typename T >
    inline T read()
    {
    	T x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * w; 
    }
    
    int fpow(int x, int y)
    {
    	int res = 1;
    	for( ; y; y >>= 1, x = 1ll * x * x % mod)
    		if(y & 1) res = 1ll * res * x % mod;
    	return res; 
    }
    
    int C(int n, int m)
    {
    	return 1ll * fac[n] * inv[n - m] % mod * inv[m] % mod; 
    }
    
    int main()
    {
    	T = read <int> ();
    	for(int i = (pow[0] = fac[0] = 1); i <= 100000; i++)
    	{
    		fac[i] = 1ll * fac[i - 1] * i % mod;
    		if(i == 1) pow[i] = 1ll * pow[0] * fpow(2, mod - 2) % mod;
    		else pow[i] = 1ll * pow[i - 1] * pow[1] % mod;
    	}
    	inv[100000] = fpow(fac[100000], mod - 2);
    	for(int i = 99999; i >= 0; i--)
    		inv[i] = 1ll * inv[i + 1] * (i + 1) % mod; 
    	while(T--)
    	{
    		n = read <int> (), k = read <int> (); 
    		ans = 0; 
    		if(!((n - k) & 1))
    		{
    			printf("%d ", (fpow(2, k) - 1 + mod) % mod); 
    			for(int op = (k & 1 ? mod - 1 : 1), i = 0; i <= k; i++, op = mod - op)
    				ans = (ans + 1ll * op * C(k, i) % mod * fpow(2 * i - k + mod, n) % mod) % mod; 
    			ans = 1ll * ans * pow[k] % mod; 
    			printf("%d
    ", ans); 
    		}
    		else
    		{
    			printf("%d ", (fpow(2, k) - 2 + mod) % mod);
    			for(int op = (k & 1 ? 1 : mod - 1), i = 0; i < k; i++, op = mod - op)
    				ans = (ans + 1ll * op * C(k - 1, i) % mod * (fpow(2 * i - k + 2 + mod, n) + fpow(2 * i - k + mod, n)) % mod) % mod;
    			ans = 1ll * ans * pow[k] % mod;
    			printf("%d
    ", ans); 
    		}
    	}
    	return 0; 
    }
    
  • 相关阅读:
    CSS3学习手记(7) CSS3装换 3D转换
    CSS3学习手记(6) CSS3装换 2D转换
    CSS3学习手记(5) 渐变
    CSS3学习手记(4) 伪元素
    CSS3学习手记(3) CSS权重
    CSS3学习手记(2) 伪类选择器
    CSS3学习手记(1) 选择器
    HTML5学习手记(二)
    HTML5学习手记(一)
    浏览器远程调试VS
  • 原文地址:https://www.cnblogs.com/ztlztl/p/12208179.html
Copyright © 2020-2023  润新知