• [HAOI2018]奇怪的背包


    题目链接

    题目大意

    有一个模P意义下的背包,n个物品,每种有无限个,q个询问,问重量为w的方案。
    题解:
    首先,先考虑如何判断一些物品能否组成重w的背包。
    根据贝祖定理,只要这些数和P的最大公约数是w的约数,就可以。

    所以,对于本题,就是判断(2^n)中方案中,有多少种方案使得选择的数和P的最大公约数是w的约数。
    显然,有一个(O((n+q)*约数个数))的dp,会超时。

    考虑优化:
    对于询问,枚举w的约数x,根据之前的分析,只有x是P的约数才有解。
    所以,枚举(gcd(w,P))的约数即可。
    由于P的约数不多,所以可以枚举P的约数y,预处理(gcd(w,P)=y)时的答案。
    对于DP个过程,也可以用类似的方法:
    由于要和P取gcd,所以每个V与(gcd(V,P))等价,而不同的(gcd(V,P))只有(O(P的约数个数))个。
    这样,枚举(gcd(V,P))进行DP,就行了。
    由于要用map定位约数,时间复杂度为(O(M^2logM+(n+q)logP)),能过。(M为P的约数个数)

    代码

    #include <stdio.h> 
    #include <map> 
    using namespace std;
    #define md 1000000007 
    map < int,int > mp;
    int gcd(int a, int b) {
    	while (b != 0) {
    		int t = a % b;
    		a = b;
    		b = t;
    	}
    	return a;
    }
    int ys[1500],m = 0,dp[1500][1500],sl[1500],mi[1000010],ans[1500];
    int main() {
    	int n,q,P;
    	scanf("%d%d%d", &n, &q, &P);
    	for (int i = 1; 1ll * i * i <= P; i++) {
    		if (P % i == 0) {
    			ys[m++] = i;
    			if (P / i != i) ys[m++] = P / i;
    		}
    	}
    	for (int i = 0; i < m; i++) mp[ys[i]] = i;
    	for (int i = 0; i < n; i++) {
    		int a;
    		scanf("%d", &a);
    		sl[mp[gcd(P, a)]] += 1;
    	}
    	mi[0] = 1;
    	for (int i = 1; i <= n; i++) mi[i] = (mi[i - 1] + mi[i - 1]) % md;
    	dp[0][1] = 1;
    	for (int i = 0; i < m; i++) {
    		for (int j = 0; j < m; j++) {
    			dp[i + 1][j] = (dp[i + 1][j] + dp[i][j]) % md;
    			int t = mp[gcd(ys[j], ys[i])];
    			dp[i + 1][t] = (dp[i + 1][t] + 1ll * (mi[sl[i]] - 1 + md) * dp[i][j]) % md;
    		}
    	}
    	for (int i = 0; i < m; i++) {
    		for (int j = 0; j < m; j++) {
    			if (ys[i] % ys[j] == 0) ans[i] = (ans[i] + dp[m][j]) % md;
    		}
    	}
    	for (int i = 0; i < q; i++) {
    		int a;
    		scanf("%d", &a);
    		printf("%d
    ", ans[mp[gcd(a, P)]]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    从URL输入到页面展现,过程中发生了什么?
    Android ADB被占用 重启 ADB方法
    Android消息处理:EventBus、BroadCast和Handler-优缺点比较
    Android EventBus 的使用
    浅谈Java/Android下的注解
    如何理解Android中的xmlns
    【LeetCode】165
    【leetcode】155
    【LeetCode】12 & 13
    【LeetCode】66 & 67- Plus One & Add Binary
  • 原文地址:https://www.cnblogs.com/lnzwz/p/11354673.html
Copyright © 2020-2023  润新知