列表

详情


NC50599. 礼物

描述

一年一度的圣诞节快要来到了。每年的圣诞节小E都会收到许多礼物,当然他也会送出许多礼物。不同的人物在小E心目中的重要性不同,在小E心中分量越重的人,收到的礼物会越多。
小E从商店中购买了n件礼物,打算送给m个人,其中送给第i个人礼物数量为w_i。请你帮忙计算出送礼物的方案数(两个方案被认为是不同的,当且仅当存在某个人在这两种方案中收到的礼物不同)。由于方案数可能会很大,你只需要输出模P后的结果。

输入描述

输入的第一行包含一个正整数P,表示模数;
第二行包含两个正整数n和m,分别表示小E从商店购买的礼物数和接受礼物的人数;
以下m行每行仅包含一个正整数w_i,表示小E要送给第i个人的礼物数量。

输出描述

若不存在可行方案,则输出Impossible,否则输出一个整数,表示模P后的方案数。

示例1

输入:

100
4 2
1
2

输出:

12

说明:

12种方案详情如下:{1 } {2,3 }, {1 } {2,4 }, {1 } {3,4 }, {2 } {1,3 }, {2 } {1,4 }, {2 } {3,4 }, {3 } {1,2 }, {3 } {1,4 }, {3 } {2,4 }, {4 } {1,2 }, {4 } {1,3 }, {4 } {2,3 }。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 26ms, 内存消耗: 416K, 提交时间: 2022-06-25 13:01:03

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define N 105
int cnt,n; ll P,m,a[N];
struct node{
	ll p,sum,num,val;
}c[N];
void fzt(ll x){
	ll i;
	for (i=2; i*i<=x; i++)
	if (!(x%i))
	for(c[++cnt].p=i,c[cnt].sum=1;!(x%i);x/=i)
	{
		c[cnt].num++;
		c[cnt].sum*=i;
	}
	if (x!=1)
	{
		c[++cnt].p=x;
		c[cnt].num=1;
		c[cnt].sum=x;
	}
}
ll ksm(ll x,ll y,ll mod)
{
	ll sum=1,base=x;
	while (y)
	{
		if (y&1)
		sum=sum*base%mod;
		base=base*base%mod;
		y>>=1;
	}
	return sum;
}
void exgcd(ll u,ll v,ll &x,ll &y){
	if (!v){
		x=1;
		y=0;
		return;
	}
	else{
		exgcd(v,u%v,y,x);
		y-=x*(u/v);
	}
}
ll getivs(ll x,ll p){
	ll t1,t2; exgcd(x,p,t1,t2);
	return (t1%p+p)%p;
}
ll crt(){
	int i; ll sum=0;
	for (i=1; i<=cnt; i++){
		ll t1,t2;
		exgcd(c[i].sum,P/c[i].sum,t1,t2);
		t2=(t2%P+P)%P;
		sum=(sum+P/c[i].sum*t2*c[i].val)%P;
	}
	return (sum%P+P)%P;
}
void solve(int k,ll x,ll &t1,ll &t2){
	ll i,u,v; t1=1; t2=x/c[k].p;
	for (i=1; i<c[k].sum; i++)
	if(i%c[k].p)
	t1=t1*i%c[k].sum;
	t1=ksm(t1,x/c[k].sum,c[k].sum);
	for(i=x-x%c[k].sum+1; i<=x; i++)
	if(i%c[k].p)
	t1=t1*i%c[k].sum;
	if (t2){
		solve(k,t2,u,v);
		t1=t1*u%c[k].sum;
		t2+=v;
	}
}
int main(){
	scanf("%lld%lld%d",&P,&m,&n);
	int i,j,sum=0;
	for (i=1; i<=n; i++)
	{
		scanf("%lld",&a[i]);
		sum+=a[i];
	}
	if (sum>m)
	{
		cout<<"Impossible"<<endl;
		return 0;
	}
	if (sum<m) a[++n]=m-sum;
	fzt(P);
	for (i=1; i<=cnt; i++)
	{
		ll t1,t2; solve(i,m,t1,t2);
		for (j=1; j<=n; j++)
		{
			ll u,v;
			solve(i,a[j],u,v);
			t2-=v;
			t1=t1*getivs(u,c[i].sum)%c[i].sum;
		}
		c[i].val=t1*ksm(c[i].p,t2,c[i].sum)%c[i].sum;
	}
	printf("%lld\n",crt());
	return 0;
}

上一题