zoukankan      html  css  js  c++  java
  • Codeforces Round #365 (Div. 2) E

    http://codeforces.com/contest/703/problem/E

    题意:

    给出n个数和一个k,计算出至少要多少个数相乘才是k的倍数。

    思路:
    这道题目参考了杭电大神的代码http://blog.csdn.net/snowy_smile/article/details/52134304

    对于每个数字,我们要么选,要么不选,这就很像01背包。但是肯定是需要预处理的。

    对于每个数字,它所贡献的数就是它和k的最大公因数,这个不难理解吧。

    所以我们可以把k的所有因子计算出来,因为有些因子很大,所以这里离散化一下,用map映射,这样后面才开得了数组。

    我们用f[i][j]表示前i个数字,它们的gcd乘=映射j状态时的最佳方案。

    当我们分析到第i个数字时,它所能贡献的数就是gcd(a[i],v[j]),那么它的前缀就是v[j]/gcd(a[i],v[j]),具体参见代码。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<string>
      6 #include<vector>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 using namespace std;
     11 typedef long long LL;
     12 const int maxn=1000+5;
     13 
     14 int n;
     15 LL k;
     16 LL s;
     17 LL a[maxn];
     18 LL b[maxn];
     19 pair<int,LL> f[maxn][maxn*10];
     20 vector<LL> v;
     21 map<LL,LL> key;
     22 
     23 LL gcd(LL a,LL b)
     24 {
     25     if(a<b)  swap(a,b);
     26     while(b!=0)
     27     {
     28         LL t=a;
     29         a=b;
     30         b=t%b;
     31     }
     32     return a;
     33 }
     34 
     35 void dp()
     36 {
     37     if(k==1)
     38     {
     39         puts("1");
     40         LL tmp =0x3f3f3f3f3f3f3f3f, ans=-1;
     41         for (int i = 1; i<=n;++i)
     42             if (a[i]<=tmp)
     43             {
     44                 ans=i;
     45                 tmp=a[i];
     46             }
     47         printf("%lld
    ", ans);
     48         return;
     49     }
     50     for(int j=1;j<s;j++)   f[0][j]=make_pair(n+1,0);
     51     for(int i=1;i<=n;i++)
     52     {
     53         for (int j = 0; j < s; ++j)
     54         {
     55             f[i][j] = f[i - 1][j];
     56             int pre = key[v[j] / gcd(v[j], b[i])];
     57             f[i][j]=min(f[i][j], make_pair(f[i - 1][pre].first + 1, f[i - 1][pre].second + a[i]));
     58         }
     59     }
     60     if (f[n][s-1].first > n) puts("-1");
     61     else
     62     {
     63         printf("%d
    ", f[n][s-1].first);
     64         for (int i = n; i; --i)
     65         {
     66             if (f[i][key[k]] != f[i - 1][key[k]])
     67             {
     68                 printf("%d ", i);
     69                 k /= gcd(k, b[i]);
     70             }
     71         }
     72         puts("");
     73     }
     74 }
     75 
     76 int main()
     77 {
     78     //freopen("D:\input.txt","r",stdin);
     79     while(~scanf("%d%lld",&n,&k))
     80     {
     81         LL m=sqrt(k+0.5);
     82         v.clear();
     83         for(int i=1;i<=m;i++)
     84         {
     85             if(k%i==0)
     86             {
     87                 v.push_back(i);
     88                 if(k/i!=i)  v.push_back(k/i);
     89             }
     90         }
     91         sort(v.begin(),v.end());
     92         s=v.size();
     93         key.clear();
     94         for(int i=0;i<s;i++)  key[v[i]]=i;
     95         for(int i=1;i<=n;i++)
     96         {
     97             scanf("%lld",&a[i]);
     98             b[i]=gcd(k,a[i]);
     99         }
    100         dp();
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    0309. Best Time to Buy and Sell Stock with Cooldown (M)
    0621. Task Scheduler (M)
    0106. Construct Binary Tree from Inorder and Postorder Traversal (M)
    0258. Add Digits (E)
    0154. Find Minimum in Rotated Sorted Array II (H)
    0797. All Paths From Source to Target (M)
    0260. Single Number III (M)
    0072. Edit Distance (H)
    0103. Binary Tree Zigzag Level Order Traversal (M)
    0312. Burst Balloons (H)
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6869705.html
Copyright © 2011-2022 走看看