zoukankan      html  css  js  c++  java
  • Codeforces 703E DP + 因数分解 +离散化

    题意:给你n个数,和一个数m, 问最小需要多少个数,可以让这些数乘起来是m的倍数。如果有多组,取和最小的那一组。

    思路:因为m的范围到1e12,并且和取模相关,所以容易想到处理出m的约数,然后离散化一下,降低DP的第二维的复杂度,因为如果这些数的乘积不是m的约数,就没有意义了。dp[i][j]表示处理到第i个数,约数是j的最小个数。dp需要存pair,因为要求个数一样的时候和最小。可以提前把a和m求gcd以降低复杂度,注意特判m为1的情况。

    代码:

    #include <bits/stdc++.h>
    #define LL long long
    #define pii pair<LL, LL>
    #define INF 1e16
    using namespace std;
    const int maxn = 1010;
    pii dp[maxn][7010];
    map<LL, int> mp;
    LL f[7010], tot;
    int n;
    LL m, a[maxn], b[maxn]; 
    void init(LL x) {
    	for (LL i = 1; i * i <= x; i++) {
    		if(x % i == 0) {
    			f[++tot] = i;
    			if(i * i != x)
    				f[++tot] = x / i;
    		}
    	}
    	sort(f + 1, f + 1 + tot);
    	for (int i = 1; i <= tot; i++)
    		mp[f[i]] = i;
    }
    int main() {
    	scanf("%d%lld", &n, &m);
    	init(m);
    	for (int i = 1; i <= n; i++) {
    		scanf("%lld", &a[i]);
    		b[i] = __gcd(a[i], m);
    	}
    	if(m == 1) {
    		LL ans = 1e15, pos = 0;
    		for (int i = 1; i <= n; i++) {
    			if(a[i] < ans) {
    				ans = a[i];
    				pos = i;
    			}
    		}
    		printf("%d
    %lld
    ", 1, pos);
    		return 0;
    	}
    	for (int i = 2; i <= tot; i++)
    		dp[0][i] = pii(INF, 0);
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= tot; j++) {
    			dp[i][j] = dp[i - 1][j];
    			int pos = mp[f[j] / __gcd(f[j], b[i])];
    			pii tmp = pii(dp[i - 1][pos].first + 1, dp[i - 1][pos].second + a[i]);
    			dp[i][j] = min(dp[i][j], tmp);
    		}
    	}
    	if(dp[n][tot].first > n) printf("-1
    ");
    	else {
    		printf("%lld
    ", dp[n][tot].first);
    		LL now = f[tot], pos = tot;
    		for (int i = n; i >= 1; i--) {
    			if(dp[i][pos] != dp[i - 1][pos]) {
    				printf("%d ", i);
    				now /= __gcd(b[i], now);
    				pos = mp[now];
    			}
    		}
    	}
    }
    

      

  • 相关阅读:
    SprimgMVC学习笔记(五)—— Controller方法返回值
    SprimgMVC学习笔记(四)—— @RequestMapping
    SprimgMVC学习笔记(三)—— 参数绑定
    SprimgMVC学习笔记(二)—— 整合Mybatis
    SprimgMVC学习笔记(一)—— SpringMVC入门
    mysql
    进程与线程
    xml
    生成器
    并发多线程
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10755688.html
Copyright © 2011-2022 走看看