• 洛谷P4495 [HAOI2018]奇怪的背包(数论)


    题面

    传送门

    题解

    好神仙的思路啊……orzyyb

    因为不限次数,所以一个体积为(V_i)的物品可以表示出所有重量为(gcd(V_i,P))的倍数的物品,而所有物品的总和就是这些所有的(gcd)

    那么我们把每个(V_i)转化为(gcd(V_i,P)),把(w_i)转化为(gcd(w_i,P)),题目就可以变成问有多少种选择(V_i)的方法使(V_i)(gcd)(w_i)的因子

    据说当(P)很大的时候(sigma(P))大概只有(P^{1over 3})的数量级,那么我们可以对于(P)的所有的因数预处理答案,到时候就可以(O(log P))回答了(这里的(log)是求(gcd)的复杂度)

    我们设(f_i)表示所有数的(gcd)(i)的方案数,如果有(s)个数是(i)的倍数,那么方案数就是(2^s-1),然后再减去所有(gcd)(i)的倍数的方案就行了

    复杂度为(O((n+q)log q+sigma^2(q)))

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    }
    const int N=1e6+5,M=50005,P=1e9+7;
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
    	return res;
    }
    int gcd(int x,int y){return y?gcd(y,x%y):x;}
    int id1[M],id2[M],f[M],s[M],st[M],w[M],a[N],bin[N];
    int n,q,p,tot,top,res,x;
    inline int ID(R int x){return x<M?id1[x]:id2[p/x];}
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read(),q=read(),p=read();
    	fp(i,1,n)a[i]=gcd(p,read());
    	bin[0]=1;fp(i,1,n)bin[i]=mul(bin[i-1],2);
    	fp(i,1,sqrt(p))if(p%i==0){
    		w[++tot]=i;
    		p/i!=i?w[++tot]=p/i:0;
    	}
    	sort(w+1,w+1+tot);
    	fp(i,1,tot)w[i]<M?id1[w[i]]=i:id2[p/w[i]]=i;
    	fp(i,1,n)++s[ID(a[i])];
    	fd(i,tot,1){
    		res=top=0;
    		fp(j,i,tot)w[j]%w[i]==0?(st[++top]=j,res+=s[j]):0;
    		f[i]=bin[res]-1;
    		fp(j,2,top)f[i]=dec(f[i],f[st[j]]);
    	}
    	fd(i,tot,1)fp(j,1,i-1)w[i]%w[j]==0?f[i]=add(f[i],f[j]):0;
    	while(q--)x=gcd(p,read()),print(f[ID(x)]);
    	return Ot(),0;
    }
    
  • 相关阅读:
    vector详解
    浅谈 莫斯电码&栅栏密码
    牛牛的BRD迷宫2 构造+思维
    Codeforces Round #409 C. Voltage Keepsake(二分+思维)
    hdu 2609 How many(最小表示法)
    hdu 4513(Manacher)
    codeforces 486 E. LIS of Sequence(dp)
    codeforces 486 D. Valid Sets(树形dp)
    hdu3746(kmp最小循环节)
    poj 2406 Power Strings(kmp next的应用)
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10520745.html
Copyright © 2020-2023  润新知