cf/codeforces #365 E - Mishka and Divisors 数学+背包dp+gcd

原创 2016年08月31日 13:58:41

Problem E - Mishka and Divisors

题目大意

 给n,k,给n个数,让你挑出m个数,使得m个数的乘积是k的倍数,输出最小的m。

如果有多个方案,输出sum最小的方案,(方案输出所选数的下标)

   数据范围:n <= 1000, k <= 10^12, ai<=10^12。


解题分析

  dp[i][j]表示前i个数里选一些数,使得乘积是j的倍数的最小的m。

sum[i][j]表示最优方案对应的sum

可以得知,dp[i][j]=min(dp[i-1][j],dp[i-1] [ j/gcd(j,a[i])]    )

也就是要么不选a[i],如果选a[i]就在前面选前i-1个数取到j/gcd(j,a[i])的方案

记得相应的sum值也要更新。

        

这里的i就是1到n,而j应该是 k的约数们,可以知道k的约数个数大概是lg至上,sqrt未满的一个数量级, 

粗略估计一下不超过1W ?  不过最后内存用了17X mb ...还好是cf

把k的约数们用map映射一下就好了

时间卡得紧,会T,注意到 求gcd(j,a[i])的时候,可以先令b[i]=gcd(k,a[i]),最后直接求gcd(j,b[i])能省一些时间



参考程序


 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1005;

ll aa[N];
ll bb[N];
ll prim[11000+50];
ll ok=0;
void f(ll k)
{
    for (ll i=1; i*i<=k; i++)
        if (k%i==0)
        {
            prim[++ok]=i;
            if (k/i!=i)
                prim[++ok]=k/i;
        }
}
ll dp[N][11000+50];
ll sum[N][11000+5];
map <ll,int>idx;
ll gcd(ll a,ll b)
{
    if (!b) return a;
    else return gcd(b,a%b);
}
int main()
{
    ll n,k;
    cin>>n>>k;
    ll tmp=k;
    for (int i=1; i<=n; i++)
    {
        scanf("%lld",&aa[i]);
        bb[i]=gcd(k,aa[i]);
    }
    if (k==1)
    {
        printf("1\n");
        printf("%d\n",(min_element(aa+1,aa+1+n)-aa));
        return 0;
    }
    f(k);
    sort(prim+1,prim+1+ok);
    for (int i=1; i<=ok; i++)
        idx[prim[i]]=i;
     for (int j=2; j<=ok; j++)
    {
        if (aa[1]%prim[j]==0)
            dp[1][j]=1,sum[1][j]=aa[1];
        else dp[1][j]=n+1;
    }
    dp[1][1]=0;
    for (int i=2; i<=n; i++)
    {
        for (int j=1; j<=ok; j++)
        {
            dp[i][j]=dp[i-1][j];
            sum[i][j]=sum[i-1][j];
            ll v=prim[j]/gcd(prim[j],bb[i]);
            int id=idx[v];
            if (dp[i-1][id]+1 < dp[i][j]  )
            {
                dp[i][j]=dp[i-1][id]+1;
                sum[i][j]=sum[i-1][id]+aa[i];
            }
            else if (dp[i-1][id]+1==dp[i][j])
            {
                if (sum[i][j]>sum[i-1][id]+aa[i])
                    sum[i][j]=sum[i-1][id]+aa[i];
            }
        }
    }
    if (dp[n][ok]>n)
    {
        printf("-1\n");
        return 0;
    }
    printf("%lld\n",dp[n][ok]);
    tmp=k;
    for (int i=n; i>=1; i--)
    {
        int id=idx[tmp];
        if (dp[i][id]==dp[i-1][id]&& sum[i][id]==sum[i-1][id]) continue;
        printf("%d ",i);
        tmp/=gcd(tmp,bb[i]);
    }
    printf("\n");



    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Codeforces Round #365 (Div. 2) A(暴力) B(数学技巧) C(二分)D(线段树+离散)E(乘除法DP+约数分解+map映射)

传送门:A. Mishka and Game 暴力记录两人赢的次数,最后将次数再比较一次即可 #include using namespace std; int n; int main()...

【Codeforces Round 365 (Div 2)A】【水题】Mishka and Game

A. Mishka and Game time limit per test 1 second memory limit per test 256 megabytes ...

Codeforces Round #365 (Div. 2) 703B Mishka and trip 水题

Mishka and trip time limit per test 1 second memory limit per test 256 megabytes in...
  • kyoma
  • kyoma
  • 2016年08月05日 12:59
  • 265

Codeforces 365(Div.2)A.Mishka and Game【水题】

A. Mishka and Game time limit per test 1 second memory limit per test 256 megabytes ...

Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum(树状数组)

D. Mishka and Interesting sum time limit per test 3.5 seconds memory limit per test 256 megabyte...

Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum(精简的代码)

Little Mishka enjoys programming. Since her birthday has just passed, her friends decided to present...

【Codeforces Round 365 (Div 2)B】【容斥】Mishka and trip 环加完全点图的边权乘积和

B. Mishka and trip time limit per test 1 second memory limit per test 256 megabytes ...

Codeforces Round #365 (Div. 2) B. Mishka and trip

B. Mishka and triptime limit per test 1 second memory limit per test 256 megabytes input standa...

Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum

Little Mishka enjoys programming. Since her birthday has just passed, her friends decided to present...

Codeforces Round #365 (Div. 2) -- B. Mishka and trip (找规律枚举)

B. Mishka and trip time limit per test 1 second memory limit per test 256 megabytes input...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:cf/codeforces #365 E - Mishka and Divisors 数学+背包dp+gcd
举报原因:
原因补充:

(最多只允许输入30个字)