• AtCoder Regular Contest 102 E Stop. Otherwise...


    题目链接:atcoder

    大意:有(n)个骰子,每个骰子上面有(k)个数,分别是(1 ext ~ k),现在求(forall iin[2...2k]),求出有多少种骰子点数的组合方式使得任意两个骰子的点数之和不等于(i),注意不考虑顺序

    分析

    对每个(i)计算答案

    我们知道,如果(1leq j leq i)(1leq i-j leq i)那么(j)(i-j)最多只能出现一个

    我们对于每个(i)计算出有多少组((j,i-j))满足上面的限制条件,记为(cnt)

    那么对于剩下的(k-2*cnt)的取值便变得可以出现也可以不出现了

    所以骰子点数的出现情况的方案数就是

    [sum_{q=0}^{cnt}C_{cnt}^q*2^q ]

    接下来考虑对于每一种出现情况的组合数

    假设我们当前选了(q)个限制组中的元素,我们可以列出下面这样一个方程

    [x_1+x_2+cdots+x_q+y_1+y_2+cdots+y_{k-2*cnt}=n ]

    其中(x1,x2,cdots,x_q)表示限制组中元素的出现次数,(y_1,y_2,cdots,y_{k-2*cnt})表示非限制组中的元素的出现次数

    那么依照上面的假设就有(x_i> 0,y_igeq 0),求该方程的解的组数

    将方程转化为

    [x_1+x_2+cdots+x_{cnt}+(y_1+1)+(y_2+1)+cdots+(y_{k-2*cnt}+1)=n+(k-2*cnt) ]

    那么原问题就变成了一个经典的求方程正整数解的问题了,答案为(C_{n+k-2*cnt-1}^{k-cnt-1})

    将两者乘起来即可

    注意当(i)是偶数的时候,会出现((i/2,i/2))这样的一组无意义的限制组,我们可以强制令其取或不取(取最多也只有1个),然后和上面一样的求解

    时间复杂度(O(n^2))

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    using namespace std;
    const int maxd=998244353,N=100000;
    const double pi=acos(-1.0);
    typedef long long ll;
    int n,k,c[4010][4010],bin[4010];
    
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    	while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    	return x*f;
    }
    
    void init()
    {
    	k=read();n=read();
    	int i,j;
    	c[0][0]=1;
    	for (i=1;i<=4000;i++)
    	{
    		c[i][0]=1;
    		for (j=1;j<=i;j++)
    			c[i][j]=((ll)c[i-1][j]+c[i-1][j-1])%maxd;
    	}
    	bin[0]=1;
    	for (i=1;i<=4000;i++) bin[i]=(bin[i-1]*2)%maxd;
    	//for (i=1;i<=6;i++) cout << bin[i] << " ";cout << endl;
    }
    
    ll calc(int x,int y,int z)
    {	
    	if (y<0) return 0;
    	//cout << x << " " << y << " " << z << endl; 
    	int i;ll ans=0;
    	for (i=0;i<=x&&i<=z;i++)
    	{
    		if (((i+y-1)>=0) && ((i+y-1)<=(z+y-1)))
    		{
    			//cout << i << " " << x << " " << y << " " << z << endl;
    			ans=(ans+((1ll*c[x][i]*bin[i])%maxd*c[z+y-1][i+y-1])%maxd)%maxd;
    		}
    	}
    	return ans;
    }
    
    void work()
    {
    	int i,j;
    	for (i=2;i<=k*2;i++)
    	{
    		ll ans=0;int cnt=0;
    		for (j=1;j<=k;j++)
    		{
    			int tmp=i-j;
    			if ((tmp<=k) && (tmp>=1)) cnt++;
    		}
    		//cout << i << " " << cnt << endl;
    		if (i&1)
    			ans=calc(cnt/2,k-cnt,n);
    		else 
    			ans=(calc((cnt-1)/2,k-cnt,n)+calc((cnt-1)/2,k-cnt,n-1))%maxd;
    		printf("%lld
    ",ans);
    	}
    }		
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
  • 相关阅读:
    微信支付Native扫码支付模式二之CodeIgniter集成篇
    如何使用硬盘安装debian8.3?
    使用git将代码push到osc上
    树莓派(Raspberry Pi)搭建简单的lamp服务
    win下修改mysql默认的字符集以防止乱码出现
    CodeIgniter2.2.0-在控制器里调用load失败报错的问题
    Ubuntu Server(Ubuntu 14.04 LTS 64位)安装libgdiplus2.10.9出错问题记录
    linux下mono的安装与卸载
    asp.net中ashx生成验证码代码放在Linux(centos)主机上访问时无法显示问题
    使用NPOI将数据导出为word格式里的table
  • 原文地址:https://www.cnblogs.com/encodetalker/p/10487145.html
Copyright © 2020-2023  润新知