[CEOI2004] Sweets

题目链接

  • 写出朴素的生成函数后用等比数列求和公式化简
  • 10!=3628800 \(10^6\)级别
  • 中国剩余定理可用于处理没有平方因子的合数为模数的情况
  • 本题中的模数2004含有平方因子,可以先用扩展Lucas定理求组合数再用中国剩余定理,更简便的方法是,考虑到本题中只需要除以n!,在过程中对2004*n!阶乘取模,最后再除以n!
  • 不要局限自己的优化思路
  • 通过dfsO(\(2^n\))的处理所有情况
  • 利用组合数的递推公式简化计算,不妨画出杨辉三角形
点击查看代码
#include <bits/stdc++.h>
using namespace std;
long long mod=2004,jc=1;
int m[15],n;
long long calc(int p)
{
	long long s=1;
	for(int i=0;i<n;i++)
	{
		s=s*(p-i)%mod;
	}
	return s;
}
int main()
{
	int a,b;
	cin>>n>>a>>b;
	for(int i=1;i<=n;i++)
	{
		jc=jc*i;
	}
	mod=mod*jc;
	for(int i=1;i<=n;i++)
	{
		cin>>m[i];
	}
	long long ans=0;
	for(int i=0;i<(1<<n);i++)
	{
		int sum=0,opt=1;
		for(int j=0;j<n;j++)
		{
			if(((i>>j)&1)==1)
			{
				sum=sum+m[j+1]+1;
				opt=-opt;
			}
		}
		if(sum<=b)
		{
			long long tmp=0;
			if(a-sum>0)
			{
				tmp=calc(n+b-sum)-calc(n+a-sum-1);
			}
			else
			{
				tmp=calc(n+b-sum);
			}
			ans=ans+tmp*opt%mod;
		}
	}
	ans=ans%mod;
	cout<<(((ans+mod)%mod)/jc)%2004<<endl;
	return 0;
}
posted @ 2024-06-26 17:45  D06  阅读(6)  评论(0编辑  收藏  举报