zoukankan      html  css  js  c++  java
  • [HAOI2018] 奇怪的背包

        套着dp外套的数论题hhhhh。

        不难推出以下的几个性质:

            1.第i种物品能表示的数 -> gcd(V[i] , P) 的倍数。

            2.查询W[i] 其实就相当于查询 gcd(W[i] , P).

            3.在%P同余系下 ,ax + by 可以表示的数 与 gcd(a,b) 的倍数 是相同的集合。

        看起来有点突兀,但实际特别好证明,第1条其实就是个同余方程的应用;而第2条是因为,所有能被表示的数肯定都是P的约数,所以W[i]只有与P的公约数会对答案有贡献;第三条也是同余基本定理嘛qwq

        然后发现P的约数在10^9以下最多有10^3个,所以实际的物品和查询数也只有10^3级别了hhhh(很多物品与P的gcd一样的时候随便取一个非空子集就相当于选了这种gcd的物品)

        我们就可以先开开心心dp 出 f[i][j] 表示考虑了前i种物品,且目前的gcd是j的方案数,最后对于P的每个约数k,处理出它可以被表示的方案数(也就是Σf[last][j] * [j|k])。

        以上两个部分都是 O(P约数个数 ^2) 的,轻轻松松过本题 (由于偷懒我用了STL的hashmap,还差点被卡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;
    }
    

      

  • 相关阅读:
    经典SQL语句大全
    《构建高性能Web站点》观后感
    网搜索引擎架构设计
    使用Windows系统的几个好的习惯
    静态页面对seo优化之详解
    让您SEO学习时间缩短一半的高阶秘籍
    java链表
    GAE 数据存储——事务
    GAE 博客——B3log Solo 0.2.0 发布了!
    Wine 1.3.7 发布
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8966837.html
Copyright © 2011-2022 走看看