bzoj 5302: [Haoi2018]奇怪的背包

Posted Boss.Pi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 5302: [Haoi2018]奇怪的背包相关的知识,希望对你有一定的参考价值。

Description

Solution

首先 \\(v_1,v_2,v_3...v_n,P\\) 能够构成的最小数是 \\(gcd(P,v_1,v_2,v_3...v_n)\\)
然后 \\(gcd(P,v_1,v_2,v_3...v_n)|w_i\\) 则可以构成 \\(w_i\\)
所以我们直接背包一下就可以了,设 \\(m\\)\\(P\\) 的约数个数,\\(m\\) 最多是 \\(n^{\\frac{1}{3}}\\)
那么复杂度就是 \\(O(n*m*logP)\\)
容易发现如果 \\(gcd(v_i,P)=gcd(v_j,P)\\) ,那么 \\(v_i,v_j\\) 对答案的影响是一样的,把相同类型的一起处理,把答案乘上 \\(2^{cnt}-1\\) 就行了
复杂度 \\(O(m^2*logP)\\)

#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
	int f;char c;
	for(f=1,c=getchar();c<\'0\'||c>\'9\';c=getchar())if(c==\'-\')f=-1;
	for(x=0;c<=\'9\'&&c>=\'0\';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=1e6+10,mod=1e9+7;
int n,Q,P,num=0,a[N],m=0,c[N],f[2010][2010],bin[N],ans[N];
map<int,int>id;
inline void priwork(){
   for(int i=1;i*i<=P;i++)
		if(P%i==0){
			a[++m]=i;
			if(i*i!=P)a[++m]=P/i;
		}
	sort(a+1,a+m+1);
	for(int i=1;i<=m;i++)id[a[i]]=i;
}
inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  cin>>n>>Q>>P;
  priwork();
  int x;bin[0]=1;
  for(int i=1;i<=n;i++)gi(x),c[id[gcd(x,P)]]++,bin[i]=bin[i-1]*2%mod;
  f[0][m]=1;
  for(int i=1;i<=m;i++){
	  for(int j=1;j<=m;j++){
		  if(c[i]){
			  int p=id[gcd(a[i],a[j])];
			  f[i][p]=(f[i][p]+1ll*f[i-1][j]*(bin[c[i]]-1))%mod;
		  }
		  f[i][j]=(f[i][j]+f[i-1][j])%mod;
	  }
  }
  for(int i=1;i<=m;i++)
	  for(int j=1;j<=i;j++)
		  if(a[i]%a[j]==0)ans[i]=(ans[i]+f[m][j])%mod;
  while(Q--){
	  gi(x);
	  printf("%d\\n",ans[id[gcd(x,P)]]);
  }
  return 0;
}

以上是关于bzoj 5302: [Haoi2018]奇怪的背包的主要内容,如果未能解决你的问题,请参考以下文章

haoi2018奇怪的背包题解

bzoj 5306 [HAOI2018] 染色

bzoj 5305 [Haoi2018] 苹果树

bzoj 5305: [Haoi2018]苹果树

bzoj 5306: [Haoi2018]染色

[HAOI2018]奇怪的背包 (DP,数论)