• jzoj 6300. Count


    Description

    详见OJ

    Solution

    首先看题,我们发现(sum{a[i]}=n),所以可以理解为一个抽屉问题。
    但它不仅有一条限制,而且(n)也十分的大。怎么办呢?
    %%%sls大佬%%%想到可以将(sum{a[i]})拆分成(sum{b[i]*m+p[i]}(p[i]<m))
    而对于(b[i])可以用组合数直接求,那么对于(p[i])呢?
    我们不妨看看几个式子:
    (sum{p[i]}≡n(mod m))
    (sum{p[i]} <= k*(m - 1))
    所以我们可以枚举(sum{p[i]})
    但是,如果直接用组合数的话有些(p[i])可能会超过(m - 1),这样我们就需要用到容斥了。
    我们再枚举有多少个数(设为(j))超过了(m-1),然后先将(sum{p[i]})减去(j*(m-1))
    求出组合数后再将它任意放回去即可。最后不要忘了(b[i])的组合数。

    Code

    #include <cstdio>
    #define N 5010
    #define maxn 10000000 
    #define ll long long
    #define mo 998244353
    #define mem(x, a) memset(x, a, sizeof x)
    #define fo(x, a, b) for (int x = a; x <= b; x++)
    #define fd(x, a, b) for (int x = a; x >= b; x--)
    using namespace std;
    int m, K, nmm;
    ll n, ans = 0, s;
    ll jc[maxn + 10], ny[maxn + 10];
    
    ll ksm(ll x, int y)
    {
    	ll s = 1;
    	while (y)
    	{
    		if (y & 1) s = s * x % mo;
    		x = x * x % mo; y >>= 1;
    	}
    	return s;
    }
    
    ll C(int x, int y) {return x > y ? 0 : jc[y] * ny[x] % mo * ny[y - x] % mo;}
    
    ll calc(ll x, ll y)
    {
    	if (x > y) return 0;
    	ll s = 1;
    	for (ll i = y - x + 1; i <= y; i++) s = s * (i % mo) % mo;
    	s = s * ny[x] % mo;
    	return s;
    }
    
    int main()
    {
    	freopen("count.in", "r", stdin);
    	freopen("count.out", "w", stdout);
    	scanf("%lld%d%d", &n, &m, &K); nmm = n % m;
    	if (m == 1) {puts("0"); return 0;}
    	if (K == 1) {printf("%d
    ", n % m == 0 ? 0 : 1); return 0;}
    	jc[0] = ny[0] = 1;
    	fo(i, 1, maxn) jc[i] = jc[i - 1] * i % mo;
    	ny[maxn] = ksm(jc[maxn], mo - 2);
    	fd(i, maxn - 1, 1) ny[i] = ny[i + 1] * (i + 1) % mo;
    	for (ll sump = nmm; sump <= K * (m - 1); sump += m)
    	{
    		s = 0;
    		fo(i, 0, K)
    		{
    //			printf("%lld %lld
    ", K - 1, sump - i * (m - 1) - 1);
    			s = (s + C(K - 1, sump - i * (m - 1) - 1) * C(i, K) % mo * ((i & 1) ? -1 : 1)) % mo;
    		}
    //		printf("%lld %lld
    ", sump, s);
    		ans = (ans + s * calc(K - 1, K + (n - sump) / m - 1) % mo) % mo;
    //		printf("%lld
    ", ans);
    	}
    	printf("%lld
    ", (ans + mo) % mo);
    	return 0;
    }
    
    转载需注明出处。
  • 相关阅读:
    Monitor All SQL Queries in MySQL (alias mysql profiler)
    to config RBS/RBLOB in sharepoint
    Chapter 10 EF 6 Support
    分布式网站架构后续:zookeeper技术浅析
    js中的json对象详细介绍
    JS通用方法总结(一)
    combobox远程加载数据的总结和Json数据的小结
    iframe自适应方法
    简单理解Hibernate三种状态的概念及互相转化
    hibernate的save()和persit()之间的区别
  • 原文地址:https://www.cnblogs.com/jz929/p/11348629.html
Copyright © 2020-2023  润新知