Mysterious For

一、题目

点此看题

题目描述

m m 个循环,分为两类,第一类循环从 [ 1 , n ] [1,n] ,第二类从上一个变量开始循环到 n n ,有 k k 个一类循环,问最终会循环多少次,答案模一个数 364875103 364875103

二、解法

可以把原问题变成 k k 个子问题,然后利用乘法原理即可。

考虑一个循环个数为 t t 的子问题,可以转化为 t t 个不同的小球, n n 的相同的盒子,盒子可以为空,所以我们先把每个盒子放一个球,然后用插板法可以算出方案数是 C ( n + t 1 , t ) C(n+t-1,t)

然后给出的这个模数可以分解成一个质数 97 97 和另一个质数, 97 97 l u c a s lucas 处理即可,另一个较大的质数直接预处理阶乘,最后用普通 c t r ctr 合并即可。

#include <cstdio>
#define M 1100005
#define int long long
const int M1 = 97;
const int M2 = 364875103/97;
const int MOD = 364875103;
int read()
{
    int x=0,flag=1;char c;
    while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
    while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*flag;
}
int T,n,m,k,r1,r2,ans,a[20],fac[M],inv[M],f1[100];
void init()
{
	fac[0]=inv[0]=inv[1]=f1[0]=1;
	for(int i=2;i<M;i++) inv[i]=inv[M2%i]*(M2-M2/i)%M2;
	for(int i=1;i<M;i++) inv[i]=inv[i]*inv[i-1]%M2;
	for(int i=1;i<M;i++) fac[i]=fac[i-1]*i%M2;
	for(int i=1;i<100;i++) f1[i]=f1[i-1]*i%M1;
}
int qkpow(int a,int b,int p)
{
	int r=1;
	while(b>0)
	{
		if(b&1) r=r*a%p;
		a=a*a%p;
		b>>=1;
	}
	return r;
}
int C(int n,int m)
{
	if(n<m) return 0;
	return f1[n]*qkpow(f1[m]*f1[n-m]%M1,M1-2,M1)%M1;
}
int lucas(int n,int m)
{
	if(m==0) return 1;
	return lucas(n/M1,m/M1)*C(n%M1,m%M1)%M1;
}
signed main()
{
	init();
	T=read();
	for(int Cs=1;Cs<=T;Cs++)
	{
		n=read();m=read();k=read();
		for(int i=1;i<=k;i++)
			a[i]=read();
		a[++k]=m;r1=r2=1;
		for(int i=2;i<=k;i++)
		{
			int t=a[i]-a[i-1];
			r1=r1*lucas(n+t-1,t)%M1;
			r2=r2*fac[n+t-1]%M2*inv[t]%M2*inv[n-1]%M2;
		}
		ans=(r1*M2*qkpow(M2,M1-2,MOD)+r2*M1*qkpow(M1,M2-2,MOD))%MOD;
		printf("Case #%lld: %lld\n",Cs,ans);
	}
}
原创文章 430 获赞 14 访问量 1万+

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/105794167