DZY Loves Math II

内存限制:512 MiB 时间限制:2000 ms 标准输入输出
题目类型:传统  评测方式:文本比较

输入格式

第一行,两个正整数 S 和 q,q 表示询问数量。
接下来 q 行,每行一个正整数 n。

输出格式

输出共 q 行,分别为每个询问的答案。

对于100%的数据,2<=S<=2*10^6,1<=n<=10^18,1<=q<=10^5;

 

 题解:

我们发现对于每一个S,他一定能分成若干个质数乘积的形式,否则他就不能满足第四条条件,同时S的质因子个数一定小于等于7;   

解释:2*3*5*7*11*13*17*19=9699690>2*10^6;

其次,n的范围又太大,导致不能直接跑多重背包;

我们发现S一定是每个质因子的倍数;

因此我们可以把每一个n分成a*S+b的形式,其中a不一定等于n/S,同理b并不一定等于n mod S;

将每个n分成整块与零散块,对于整块的部分,直接用组合数求出;对于零散块,容纳最大的数值为 S的质因子个数*S,这个大小的多重背包开的下;

最后只需将   每一种零散块的方案数乘上整块的方案数 相加即为所求;

附上代码

 

查看代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int mod=1000000007;
ll S,m;
ll prime[11];
ll dp[14000005];
ll inv[10];
ll invv[10];//逆 
ll tot=0;//因子个数 
ll lp=0;//一个因子和 
ll n=0;
inline ll max(ll a,ll b){
	return a>b?a:b;
}
void bag(){
	ll maxn=S*tot; 
 	dp[0]=1;
 	for(int j=1;j<=tot;j++){
 		for(ll i=0;i+prime[j]<=maxn;++i){
 			dp[i+prime[j]]=(dp[i]+dp[i+prime[j]])%mod;
		}
		for(ll i=maxn;i>=0;--i){
			if(i+S<=maxn)dp[i+S]=(dp[i+S]-dp[i]+mod)%mod;//去重 
		}
	}
}
int main(){
	scanf("%lld%lld",&S,&m);
	ll now=S;
	ll p=sqrt(S+0.5);
	for(ll i=2;i<=p;i++){
		if(now%i==0){
			ll cnt=0;
			prime[++tot]=i;
			lp+=i;
			while(now%i==0){
				now/=i;
				cnt++;
			}
			if(cnt>1){
				while(m--){
					scanf("%lld",&n);
					printf("0\n");
				}
				return 0;
			}
		}
	}
	if(now!=1){
		prime[++tot]=now;
		lp+=now;
	}
//	for(int i=1;i<=tot;i++){
//		printf("%d ",prime[i]);
//	}
//	printf("\n");
	bag();
	inv[0]=invv[1]=inv[1]=1;
	for(int i=2;i<=7;i++){
		invv[i]=(mod+(-(mod/i)*invv[mod%i]%mod))%mod;
		inv[i]=inv[i-1]*invv[i]%mod;
	}//求逆元 
	while(m--){
		scanf("%lld",&n);
		n-=lp;
		if(n<0){
			printf("0\n");
			continue;
		}
		if(n<S){
			printf("%lld\n",dp[n]);
			continue;
		}
		ll maxp=n/S;
		ll ans=0;
		ll o=max(ans,maxp-tot+1);
		for(ll i=o;i<=maxp;i++){
			ll tmp=inv[tot-1]%mod;
            for(int j=0;j<tot-1;j++)tmp=tmp*((i-1+tot-j)%mod)%mod;//实质就是求组合数 
            ans=(ans+tmp*dp[n-i*S]%mod)%mod;
		}
		printf("%lld\n",ans%mod); 
	}
	
	
	
	
	
	
	return 0;
}

 

posted @ 2022-05-19 11:57  sandom  阅读(129)  评论(3编辑  收藏  举报