[HAOI2018] Strange backpack

 

    A number thesis in a dp coat hhhhh.

    It is not difficult to infer the following properties:

        1. The number that the i-th item can represent -> a multiple of gcd(V[i] , P).

        2. Querying W[i] is actually equivalent to querying gcd(W[i] , P).

        3. Under the %P congruence system, the numbers that can be represented by ax + by are the same set as the multiples of gcd(a,b).

    It seems a bit awkward, but it is actually very good to prove that the first item is actually an application of a congruence equation; and the second item is because all numbers that can be represented are definitely divisors of P, so W[i] has only The common divisor with P will contribute to the answer; the third is also the fundamental theorem of congruence qwq

    Then I found that the divisor of P is at most 10^3 below 10^9, so the actual number of items and queries is only 10^3 level hhhh (when many items are the same as the gcd of P, just take a non-empty subset. Equivalent to selecting this gcd item)

    We can first happily dp out f[i][j], which means that the first i items are considered, and the current gcd is the number of solutions for j. Finally, for each divisor k of P, it can be represented by processing (that is, Σf[last][j] * [j|k]).

    The above two parts are O(P subnumber ^2), and this problem is easily passed (due to being lazy, I used the hashmap of STL, and I almost got stuck hhhh)

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int ha = 1000000007;
int gcd(int x,int y){ return y?gcd(y,x%y):x;}
inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
unordered_map<int,int> N,F[2],ANS;
unordered_map<int,int> ::iterator it,IT;
int n,now,T,Q,P,nxt,to;
inline int read(){
	int x=0; char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
	return x;
}
inline void W(int x){ if(x>=10) W(x/10); putchar(x%10+'0');}
inline void update(int x){ if(!N.count(x)) N[x]=2; else (N[x]*=2)%=ha;}

inline void dp(){
    now=0,nxt=F[0][P]=1;
    int cnt=0;
	for(it=N.begin();it!=N.end();now=nxt,nxt^=1,++it){
		F[nxt].clear(),cnt++;
		for(IT=F[now].begin();IT!=F[now].end();++IT){
			ADD(F[nxt][IT->first],IT->second);
			ADD(F[nxt][gcd(IT->first,it->first)],add(it->second,ha-1)*(ll)IT->second%ha);
		}
	}
	
	for(int i=1;i*(ll)i<=P;i++) if(!(P%i)) ANS[i]=ANS[P/i]=0;
	for(it=ANS.begin();it!=ANS.end();++it)
	    for(IT=F[now].begin();IT!=F[now].end();++IT) if(!(it->first%IT->first)) ADD(it->second,IT->second);
}

inline void solve(){ while(Q--) W(ANS[gcd(read(),P)]),puts("");}

int main(){
	scanf("%d%d%d",&n,&Q,&P);
	for(int i=1;i<=n;i++) update(gcd(read(),P));
	dp(),solve();
	return 0;
}

  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325072507&siteId=291194637