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

    题意简述

    有一个奇怪的背包,它有一个参数 (P) ,当背包内放入若干个物品后,背包的重量是物品总体积对 (P) 取模后的结果。

    现有 (n) 种体积不同的物品,第 (i) 种占用体积为 (V_i) ,每种物品都有无限个。
    (q) 次询问,每次询问给出重量 (w_i) ,求有多少种放入物品的方案,能将一个初始为空的背包的重量变为 (w_i) 。注意,两种方案被认为是不同的,当且仅当放入物品的种类不同,而与每种物品放入的个数无关。不难发现总的方案数为 (2^n)
    结果对 998244353 取模。

    (n,qleq 10^6) (Pleq 10^9)


    想法

    很显然能推出要取与 (P)(gcd) 的性质。
    预处理出 (P) 的所有因数(个数是 (10^3)) 级别,然后随便 (dp) 或容斥就好了。
    有点容易想错,写之前一定要想清楚。

    (我好懒)


    总结

    性质

    一个大数 (P) 的因子个数是 (P^{frac{1}{3}}) 级别的。


    代码

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<map>
    
    #define mod 1000000007
    
    using namespace std;
    
    int read(){
    	int x=0;
    	char ch=getchar();
    	while(!isdigit(ch)) ch=getchar();
    	while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    	return x;
    }
    
    const int N = 1000005;
    
    map<int,int> mp;
    int n,Q,P,m,v[N],p[N],t[N],f[N],g[N],ans[N];
    int gcd(int a,int b) { return b?gcd(b,a%b):a; }
    int Pow_mod(int x,int y) {
    	int ret=1;
    	while(y){
    		if(y&1) ret=1ll*ret*x%mod;
    		x=1ll*x*x%mod;
    		y>>=1;
    	}
    	return ret;
    }
    int Plus(int x,int y) { return x+y>=mod?x+y-mod:x+y; }
    int Minus(int x,int y) { return x>=y?x-y:x-y+mod; }
    
    int main()
    {
    	n=read(); Q=read(); P=read();
    	for(int i=1;i<=n;i++) v[i]=gcd(P,read());
    	
    	for(int i=1;i*i<=P;i++) {
    		if(P%i) continue;
    		p[++m]=i;
    	}
    	for(int i=m;i>0;i--){
    		if(p[i]*p[i]==P) continue;
    		p[++m]=P/p[i];
    	}
    	for(int i=1;i<=m;i++) mp[p[i]]=i;
    	for(int i=1;i<=n;i++) t[mp[v[i]]]++;
    	
    	for(int i=1;i<=m;i++){
    		g[i]=t[i];
    		for(int j=i+1;j<=m;j++)
    			if(p[j]%p[i]==0) g[i]+=t[j];
    		g[i]=Minus(Pow_mod(2,g[i]),1);
    	}
    	for(int i=m;i>0;i--){
    		f[i]=g[i];
    		for(int j=i+1;j<=m;j++)
    			if(p[j]%p[i]==0) f[i]=Minus(f[i],f[j]);
    	}
    	for(int i=1;i<=m;i++){
    		ans[i]=Plus(ans[i],f[i]);
    		for(int j=i+1;j<=m;j++)
    			if(p[j]%p[i]==0) ans[j]=Plus(ans[j],f[i]);
    	}
    	
    	int w;
    	while(Q--){
    		w=gcd(read(),P);
    		printf("%d
    ",ans[mp[w]]);
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    几种流行Webservice框架性能对比
    java实现的单点登录
    SQL Server性能调优——报表数据库与业务数据库分离
    控制台console输出信息原理理解
    查看程序是否启动或者关闭--比如查看Tomcat是否开启!直接用ps命令查看进程就行了啊
    Tomcat日志问题
    客户端用httpurlconnection来进行http连接的
    一个tomcat上放多个webapp问题,那这多个webapp会不会竞争端口呢?不会!安全两码事
    ps -ef能列出进程号,和端口号没任何关系
    Tomcat打印运行时日志(控制台),访问日志,启动日志
  • 原文地址:https://www.cnblogs.com/lindalee/p/12676502.html
Copyright © 2011-2022 走看看