题目

小 CC 非常擅长背包问题,他有一个奇怪的背包,这个背包有一个参数 PP ,当他 向这个背包内放入若干个物品后,背包的重量是物品总体积对 PP 取模后的结果. 现在小 CC 有 nn 种体积不同的物品,第 ii 种占用体积为 V_iV

i

​ ,每种物品都有无限个. 他会进行 qq 次询问,每次询问给出重量 w_iw

i

​ ,你需要回答有多少种放入物品的方 案,能将一个初始为空的背包的重量变为 w_iw

i

​ .注意,两种方案被认为是不同的, 当且仅当放入物品的种类不同,而与每种物品放入的个数无关.不难发现总的方 案数为 2^n2

n

. 由于答案可能很大,你只需要输出答案对1e9+7取模的结果.

输入格式

从文件 knapsack.inknapsack.in 中读入数据. 第一行三个整数 nn , qq , PP ,含义见问题描述. 接下来一行 nn 个整数表示 V_iV

i

​ . 接下来一行 qq 个整数表示 w_iw

i

​ .

输出格式

输出到文件 knapsack.outknapsack.out 中. 输出 qq 行,每行一个整数表示答案.

输入样例

3 3 6

1 3 4

5 2 3

输出样例

5

6

6

提示

题解

考虑数论中的\(ax + by\)这样线性组合的形式,其只能表示\(gcd(a,b)\)的倍数

\(ax \mod P\)可以写成\(ax - Py\),也是\(a\)与\(P\)的线性组合

所以一个物品只能表示\(gcd(V[i],P)\)的倍数

我们只需要求出所有\(P\)的约数的方案数,对于询问\(W[i]\),我们只需要查询\(gcd(W[i],P)\)的倍数的方案数

设\(f[i][j]\)表示前\(i\)个数凑出以约数\(j\)为线性组合中的最小值的方案数【即\(j\)对其倍数的贡献】,转移即可

\(10^9\)以内约数最大不超过\(10^3\)个

建议别用STL

#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
#define MAP map<int,int>
#define res register
using namespace std;
const int maxn = 1000005,maxm = 100005,INF = 1000000000,md = 1e9 + 7;
inline int read(){
res int out = 0,flag = 1; res char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
inline void write(int x){if (x >= 10) write(x / 10); putchar(x % 10 + '0');}
MAP f[2],Ans,A;
MAP::iterator it,IT;
int n,m,P;
inline int add2(int x,int y){x += y; if (x >= md) x -= md; return x;}
inline void add(int& x,int y){x += y; if (x >= md) x -= md;}
inline int gcd(int a,int b){return b ? gcd(b,a % b) : a;}
void init(){
int tmp,p = 1; f[0][P] = 1;
for (IT = A.begin(); IT != A.end(); IT++,p ^= 1){
f[p].clear();
for (it = f[p ^ 1].begin(); it != f[p ^ 1].end(); it++){
add(f[p][it->first],it->second);
tmp = gcd(IT->first,it->first);
add(f[p][tmp],1ll * add2(IT->second,md - 1) * it->second % md);
}
}
p ^= 1;
for (res int i = 1; 1ll * i * i <= P; i++) Ans[i] = Ans[P / i] = 0;
for (it = Ans.begin(); it != Ans.end(); it++)
for (IT = f[p].begin(); IT != f[p].end(); IT++)
if (it->first % IT->first == 0)
add(it->second,IT->second);
}
void solve(){
while (m--) write(Ans[gcd(read(),P)]),puts("");
}
int main(){
n = read(); m = read(); P = read();
int x;
for (res int i = 1; i <= n; i++){
x = gcd(read(),P);
if (!A.count(x)) A[x] = 2;
else A[x] = A[x] * 2 % md;
}
init();
solve();
return 0;
}

最新文章

  1. SQLPlus 在连接时通常有四种方式
  2. 线程Thread
  3. iOS图片编辑功能实现
  4. 创建一个叫做People的类: 属性:姓名、年龄、性别、身高 行为:说话、计算加法、改名 编写能为所有属性赋值的构造方法; (2)创建主类: 创建一个对象:名叫“张三”,性别“男”,年龄18岁,身高1.80; 让该对象调用成员方法: 说出“你好!” 计算23+45的值 将名字改为“李四”
  5. Oracle优化查询技巧
  6. C#常用IO流与读写文件
  7. ls命令大全
  8. 老叶观点:MySQL开发规范之我见
  9. Android开发效率—Eclipse快捷键
  10. python time模块详解
  11. Cocos2dx坐标转换
  12. Less合并
  13. Analyzing &#39;enq: HW - contention&#39; Wait Event (Doc ID 740075.1)
  14. Jmeter(三十九)获取响应结果中参数出现的次数(转载)
  15. MAMP 安装phpredis 扩展
  16. mongodb centos7上的安装
  17. hbase 修复 hbck
  18. es6新特性之 class 基本用法
  19. PHP——smarty模板(第二天)
  20. IO流入门-第十章-DataInputStream_DataOutputStream

热门文章

  1. python_51_函数返回值1
  2. springmvc如何获取参数
  3. dojo中类的继承
  4. 阿里云服务器下安装LAMP环境(CentOS Linux 6.3) 安装与配置 FTP 服务器
  5. tomcat服务器用Servlet类查找磁盘文件上的Json信息,如果匹配则在浏览器上显示出该条内容的全部信息
  6. node第一天
  7. 通过LDB_PROCESS函数使用逻辑数据库
  8. SQL初次接触
  9. django之路由分发
  10. poj 3273 分期问题 最大化最小值