[HAOI2018]奇怪的背包
暴力\(dp\)好有道理啊
于是我们来个反演吧
考虑一个体积序列\(\{v_1,v_2,...v_n\}\)能凑成\(w\)的条件
显然是
\]
根据贝祖定理,我们知道上面的同余方程有解的条件是
\]
现在题目转化成了求有多少个子集满足\(gcd(v_1,v_2..v_n,P)|w\)了
显然一个暴力\(dp\)记录一下当前\(gcd\)转移就好了,由于\(gcd\)必然是\(P\)的约数,\(P\)的约数是\(\sqrt{P}\)级别,我们我们只存这些有用的状态,之后每次暴力转移就好了,复杂度\(O(n\sqrt{P})\)就没了
但是我们来反演一波吧
设\(F(n)\)表示有多少个子集的\(gcd\)是\(n\)的倍数,\(f(n)\)表示有多少个子集的\(gcd\)是\(n\)
非常显然存在
\]
反演可得
\]
\(F(n)\)我们随便搞一搞就好了,若有\(s\)个数都有\(n\)这个约数,那么\(F(n)=2^s-1\)
之后反演得到\(f\),这里直接枚举\(P\)的约数,复杂度是\(O(\sigma^2(P))\),但是我们还需要求一个\(\mu\),配合线筛预处理还是挺快的
最后我们的答案是
\]
我们累加一遍就好了
复杂度很玄学,毕竟有一个\(\mu\)需要求,可能是\(O(\sigma^2(P)\sqrt{P})\)
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int maxn=1e6+5;
const int mod=1e9+7;
const int M=2e5+5;
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int d[M],F[M],ans[M],f[M],g[M];
int pw[maxn],a[maxn];
int n,m,P,Sqr,tot;
int is[M],p[M>>1],mu[M],id2[M],id1[M];
inline int find(int x) {return (x<=Sqr)?id1[x]:id2[P/x];}
inline int gcd(int a,int b) {return !b?a:gcd(b,a%b);}
inline void Init() {
is[1]=1;mu[1]=1;
for(re int i=2;i<=Sqr;i++) {
if(!is[i]) p[++p[0]]=i,mu[i]=-1;
for(re int j=1;j<=p[0]&&p[j]*i<=Sqr;j++) {
is[p[j]*i]=1;
if(i%p[j]==0) break;
mu[p[j]*i]=-1*mu[i];
}
}
for(re int i=1;i<=tot;i++)
if(d[i]<=Sqr) id1[d[i]]=i;
else id2[P/d[i]]=i;
}
inline int getMu(int x) {
if(x<=Sqr) return mu[x];
int now=1,t=x;
for(re int i=1;p[i]*p[i]<=t&&i<=p[0];i++)
if(x%p[i]==0) {
x/=p[i];
if(x%p[i]==0) return 0;
now=-1*now;
if(x==1) break;
}
if(x!=1) now=-1*now;
return now;
}
int main() {
n=read(),m=read(),P=read();
for(re int i=1;i*i<=P;i++)
if(P%i==0) {
d[++tot]=i;
if(i!=P/i) d[++tot]=P/i;
}
pw[0]=1;
for(re int i=1;i<=n;i++) pw[i]=(pw[i-1]+pw[i-1])%mod;
for(re int i=1;i<=n;i++) a[i]=read();
std::sort(d+1,d+tot+1);
Sqr=std::sqrt(P);Init();
for(re int i=1;i<=n;i++) {
int k=gcd(a[i],P);
g[find(k)]++;
}
for(re int i=1;i<=tot;i++)
for(re int j=i;j<=tot;j++) {
if(d[j]%d[i]) continue;
F[i]+=g[j];
}
for(re int i=1;i<=tot;i++) F[i]=pw[F[i]]-1;
for(re int i=1;i<=tot;i++)
for(re int j=i;j<=tot;j++) {
if(d[j]%d[i]) continue;
f[i]+=F[j]*getMu(d[j]/d[i]);
f[i]%=mod;
f[i]=(f[i]+mod)%mod;
}
for(re int i=1;i<=tot;i++)
for(re int j=i;j<=tot;j++) {
if(d[j]%d[i]) continue;
ans[j]=(ans[j]+f[i])%mod;
}
for(re int i=1;i<=m;i++) {
int x=read();
int k=gcd(x,P);
printf("%d\n",ans[find(k)]);
}
return 0;
}
[HAOI2018]奇怪的背包的更多相关文章
- 【BZOJ5302】[HAOI2018]奇怪的背包(动态规划,容斥原理)
[BZOJ5302][HAOI2018]奇怪的背包(动态规划,容斥原理) 题面 BZOJ 洛谷 题解 为啥泥萌做法和我都不一样啊 一个重量为\(V_i\)的物品,可以放出所有\(gcd(V_i,P)\ ...
- [HAOI2018]奇怪的背包 (DP,数论)
[HAOI2018]奇怪的背包 \(solution:\) 首先,这一道题目的描述很像完全背包,但它所说的背包总重量是在模P意义下的,所以肯定会用到数论.我们先分析一下,每一个物品可以放无数次,可以达 ...
- 洛谷 P4495 [HAOI2018]奇怪的背包 解题报告
P4495 [HAOI2018]奇怪的背包 题目描述 小\(C\)非常擅长背包问题,他有一个奇怪的背包,这个背包有一个参数\(P\),当他 向这个背包内放入若干个物品后,背包的重量是物品总体积对\(P ...
- BZOJ5302: [Haoi2018]奇怪的背包
BZOJ5302: [Haoi2018]奇怪的背包 https://lydsy.com/JudgeOnline/problem.php?id=5302 分析: 方程\(\sum\limits_{i=1 ...
- BZOJ5302 [HAOI2018]奇怪的背包 【数论 + dp】
题目 小 CC 非常擅长背包问题,他有一个奇怪的背包,这个背包有一个参数 PP ,当他 向这个背包内放入若干个物品后,背包的重量是物品总体积对 PP 取模后的结果. 现在小 CC 有 nn 种体积不同 ...
- haoi2018奇怪的背包题解
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5302 对于一个物品,设它体积为v,那么,在背包参数为p的情况下,它能达到gcd(v,p ...
- 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_ ...
- Luogu4495 [HAOI2018] 奇怪的背包 【扩展欧几里得算法】
题目分析: 首先打个暴力求一下$10^9$以内因子最多的数的因子个数,发现只有$1344$个. 由于有$ax+by=k*(a,b)$和2017年noip的结论,所以我们可以发现对于任意多个数$a_1, ...
- BZOJ5302 HAOI2018奇怪的背包(动态规划)
由裴蜀定理,子集S有解当且仅当gcd(S,P)|w. 一个显然的dp是设f[i][j]为前i个数gcd为j的选取方案.注意到这里的gcd一定是P的约数,所以状态数是n√P的.然后可以通过这个得到gcd ...
随机推荐
- 19、网络编程 (Socket套接字编程)
网络模型 *A:网络模型 TCP/IP协议中的四层分别是应用层.传输层.网络层和链路层,每层分别负责不同的通信功能,接下来针对这四层进行详细地讲解. 链路层:链路层是用于定义物理传输通道,通常是对某些 ...
- 【原】通过Dubbo注解实现RPC调用
启动Dubbo服务有2个方式,1是通过xml配置,2是通过注解来实现,这点和Spring相似. 采用XML配置如下: <?xml version="1.0" encoding ...
- 深入理解java虚拟机---java内存区域与内存溢出异常---2堆栈溢出
本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...
- 浅谈 JavaScript 中常用数据及其类型转换
在 JavaScript 中有一些 value 会经常碰到: [] (空数组).{} (空对象).'' (空字符串).undefined.null.0.NaN.Infinite 也会经常碰到数据类型转 ...
- phoenix使用vue--单独js(不使用app.js)
实际中不能都在一个js里 api.js app.js admin.js --vue 后台 记录下方法 static--admin--hello.js import "phoenix_html ...
- ios 九宫格
#define kViewW 40 //宽度 #define kViewH 61 //高度 #define kColCount 4 //共几列 CGFloat marginX = (self.view ...
- ios 下拉列表
#import <UIKit/UIKit.h> @class FVPullDownMenu; /** 指示器状态*/ typedef enum { IndicatorStateShow = ...
- C# 新建文档CreateNewDocument
// Copyright 2010 ESRI// // All rights reserved under the copyright laws of the United States// and ...
- php数组指针
数组指针的操作: 移动数组指针的操作: Next() 向下 同时会获得当前元素的值. Prev() 向上同时会获得当前元素的值. End() 移动到最后一个元素单元 获得最后一个元素的值 Reset( ...
- PSP软件开发过程
1. 引言 这是为了编写psp系统的软件需求分析,主要按照提供的相关需求和功能. 1.1 项目风险 风险承担者包括: 任务提出者:承担任务不能完全按照想象的做出,投入等: 软件开发者:可能不能按时交付 ...