zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:chess(数学)

    题目描述

      $dirty$在一个棋盘上放起了棋子。
      棋盘规格为$n imes m$,他希望任意一个$n imes n$的区域内都有$C$个棋子。$dirty$很快就放置好了一个满足条件的棋盘方案,但是他认为这样过于简单了,他希望知道有多少个满足条件的方案。


    输入格式

    输入三个整数$n,m,C$,含义如题所述。


    输出格式

    输出一行一个整数,表示答案对$10^9+7$取模的结果。


    样例

    样例输入:

    2 3 1

    样例输出:

    6


    数据范围与提示

    对于$20\%$的数据,$n,Kleqslant 4$;
    对于另外$20\%$的数据,$m=n$;
    对于另外$20\%$的数据,$nleqslant 50$;
    对于$100\%$的数据,$1leqslant nleqslant 100$;$1leqslant mleqslant 10^{18}$;$1leqslant Cleqslant n^2$


    题解

    又没有打正解……

    设$dp[i][j]$表示第$i$列放了$j$个的方案数。

    $m$很大,显然不能爆扫,所以还要乘上系数,那么式子就变成了:

    $$dp[i][j]=sum limits_{k=0}^j (C_n^{j-k})^{frac{m}{n}} imes dp[i-1][k]$$

    初值$dp[0][0]=1$。

    预处理系数最有时间复杂度为:$Theta(n imes c^2)$的。

    又因为选$c$个和选$n^2-c$个的方案数是一样的,所以我们可以用这种方式优化。

    但是$n=m$的点还是需要特判。

    时间复杂度:$Theta(n imes c^2)$。

    期望得分:$60$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1000000007;
    int n,c;
    long long m;
    long long C[1001][1001];
    long long dp[1001][10001],wzc[1001][10001];
    long long jc[10001],inv[10001];
    long long qpow(long long x,long long y)
    {
    	long long res=1;
    	while(y)
    	{
    		if(y&1)res=res*x%mod;
    		x=x*x%mod;
    		y>>=1;
    	}
    	return res;
    }
    void pre_work()
    {
    	C[0][0]=1;
    	for(int i=1;i<=n;i++)
    	{
    		C[i][0]=1;
    		for(int j=1;j<=i;j++)
    			C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    	}
    	jc[0]=1;
    	for(long long i=1;i<=n*n;i++)
    		jc[i]=(jc[i-1]*i)%mod;
    	inv[n*n]=qpow(jc[n*n],mod-2);
    	for(long long i=n*n;i;i--)
    		inv[i-1]=inv[i]*i%mod;
    }
    long long get_C(long long x,long long y){return ((jc[x]*inv[y])%mod*inv[x-y])%mod;}
    long long lucas(long long x,long long y)
    {
    	if(!y)return 1;
    	return (get_C(x%mod,y%mod)*lucas(x/mod,y/mod))%mod;
    }
    int main()
    {
    	scanf("%d%lld%d",&n,&m,&c);
    	pre_work();
    	if(n==m)
    	{
    		printf("%lld",lucas(n*n,c));
    		return 0;
    	}
    	if(n*n<c*2)c=n*n-c;
    	for(int i=1;i<=n;i++)
    	{
    		long long flag=m/n;
    		if(i<=m%n)flag++;
    		flag%=(mod-1);
    		for(int j=0;j<=c;j++)
    			dp[i][j]=qpow(C[n][j],flag);
    	}
    	wzc[0][0]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=0;j<=c;j++)
    			for(int k=0;k<=j;k++)
    				wzc[i][j]=(wzc[i][j]+wzc[i-1][k]*dp[i][j-k]%mod)%mod;
    	printf("%lld",wzc[n][c]);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    Ray聊天记录
    ServiceFabric极简文档-5.0 Service Fabric有状态与无状态
    ServiceFabric极简文档-5.1 编程模型选择
    Java网络编程学习A轮_08_NIO的Reactor模型
    Java网络编程学习A轮_07_基于Buffer的Socket编程
    Java网络编程学习A轮_06_NIO入门
    Java网络编程学习A轮_05_Socket编程
    Spring IOC 源码简单分析 04
    Spring IOC 源码简单分析 03
    Spring IOC 源码简单分析 02
  • 原文地址:https://www.cnblogs.com/wzc521/p/11660692.html
Copyright © 2011-2022 走看看