zoukankan      html  css  js  c++  java
  • Mishka and Divisors CodeForces

    大意: 给定$n$个数, 求选择最少的数满足积为$k$的倍数, 并且和最小

    刚开始想着暴力维护$k$的素因子向量, 用map转移, 结果T了. 看了下别的dala0题解, 不需要考虑素因子, 我们考虑k的所有因子, 用map预处理一下每个因子再转移就好了.

    总的复杂度是$O(nsigma_0(k)logk)$, 1e12以内除数函数最大值是6720, 应该是可以过的, 但这题太卡时限了, long long 的gcd跑太慢. 但是可以发现每次只对k求gcd, 可以优化到$O(nsigma_0(k)primes(k))$, 或者提前对a数组取一下gcd, 可以优化一下....

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <math.h>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <string.h>
    #include <bitset>
    #define REP(i,a,n) for(int i=a;i<=n;++i)
    #define PER(i,a,n) for(int i=n;i>=a;--i)
    #define hr putchar(10)
    #define pb push_back
    #define lc (o<<1)
    #define rc (lc|1)
    #define mid ((l+r)>>1)
    #define ls lc,l,mid
    #define rs rc,mid+1,r
    #define x first
    #define y second
    #define io std::ios::sync_with_stdio(false)
    #define endl '
    '
    using namespace std;
    typedef long long ll;
    typedef pair<int,ll> pii;
    const int P = 1e9+7, INF = 0x3f3f3f3f;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
    ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
    //head
     
     
     
     
    const int N = 1e3+10, M = 7e3+10;
    int n, sz;
    ll k, a[N], b[N];
    vector<ll> A;
    map<ll,int> S;
    pii dp[N][M];
     
    int main() {
        scanf("%d%lld", &n, &k);
        REP(i,1,n) scanf("%lld", a+i),b[i]=gcd(a[i],k);
        if (k==1) return printf("1
    %d
    ",int(min_element(a+1,a+1+n)-a)),0;
        int mx = sqrt(k+0.5);
        REP(i,1,mx) if (k%i==0) {
            A.pb(i);
            if (k/i!=i) A.pb(k/i);
        }
        sort(A.begin(),A.end());
        sz = A.size();
        REP(i,0,sz-1) S[A[i]]=i;
        REP(i,1,sz-1) dp[0][i]=pii(n+1,0);
        REP(i,1,n) REP(j,0,sz-1) {
            ll pre = S[A[j]/gcd(A[j],b[i])];
            dp[i][j] = pii(dp[i-1][pre].x+1,dp[i-1][pre].y+a[i]);
            dp[i][j] = min(dp[i][j], dp[i-1][j]);
        }
        if (dp[n][sz-1].x==n+1) return puts("-1"),0;
        printf("%d
    ", dp[n][sz-1].x);
        PER(i,1,n) if (dp[i][S[k]]!=dp[i-1][S[k]]) {
            printf("%d ", i);
            k /= gcd(k,b[i]);
        } hr;
    }
    
  • 相关阅读:
    Python的单元测试(二)
    Python的单元测试(一)
    未知道——广场式的真匿名交流网站(一)
    xpath提取多个标签下的text
    清空Github上某个文件的历史版本
    如何正确使用日志Log
    使用AWS亚马逊云搭建Gmail转发服务(三)
    玩转Windows服务系列——Windows服务小技巧
    玩转Windows服务系列——服务运行、停止流程浅析
    玩转Windows服务系列——无COM接口Windows服务启动失败原因及解决方案
  • 原文地址:https://www.cnblogs.com/uid001/p/10580456.html
Copyright © 2011-2022 走看看