• Codeforces 494D Upgrading Array


    http://codeforces.com/contest/494/problem/D

    题意:给一个数组,和一个坏质数集合,可以无数次地让1到i这些所有数字除以他们的gcd,然后要求Σf(a[i])的最大值,其中

    f(x)=f(x/p)+1,p为x的最小质数,且p不为坏质数

             f(x/p)-1 ,p为x的最小质数,且p为坏质数

    思路:我们考虑,如果f[j]取了1到j的gcd,那么对后面的决策并没有任何影响,因为我们统计的贡献,只统计1到i这个部分,不统计i以后的部分。

    略坑,不知道第一次被什么卡了超时。。就写哈希了。。

     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<map>
     7 #include<set>
     8 std::map<int,int>mp;
     9 std::set<int>b;
    10 int n,m,f[200005],g[200005],a[200005];
    11 int read(){
    12     char ch=getchar();int t=0,f=1;
    13     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    14     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
    15     return t*f;
    16 }
    17 int gcd(int a,int b){
    18     if (b==0) return a;
    19     else return gcd(b,a%b);
    20 }
    21 int F(int x){
    22     if (x<=1) return 0;
    23     if (b.count(x)) return -1;
    24     int rec=x,res=0;
    25     if (mp.find(rec)!=mp.end()) return mp[rec];
    26     int d=0,cnt=0;
    27     for (int i=2;i*i<=rec;i++){
    28         int p=i;
    29         if (x%p==0){
    30             if (b.count(p)) d=-1;else d=1;
    31             while (x%p==0) x/=p,cnt+=d;
    32         }
    33     }
    34     if (x!=1){
    35         if (b.count(x)) d=-1;else d=1;
    36         cnt+=d;
    37     }
    38     return (mp[rec]=cnt);
    39 }
    40 int main(){
    41     n=read();m=read();
    42     for (int i=1;i<=n;i++) a[i]=read();
    43     for (int i=1;i<=m;i++) {int x=read();b.insert(x);}
    44     int ans=0;
    45     g[1]=a[1];
    46     for (int i=2;i<=n;i++) g[i]=gcd(g[i-1],a[i]);
    47     for (int i=1;i<=n;i++) 
    48      ans+=F(a[i]);
    49     f[0]=ans;
    50     for (int i=1;i<=n;i++){
    51         int s=F(g[i]);
    52         f[i]=-0x3f3f3f3f;
    53         for (int j=i-1;j>=0;j--)
    54          f[i]=std::max(f[i],f[j]-s*(i-j));
    55     }
    56     ans=-0x3f3f3f3f;
    57     for (int i=0;i<=n;i++) ans=std::max(ans,f[i]);
    58     printf("%d
    ",ans);
    59 }

     还有一种贪心做法,就是从后往前取,能取就取,直到变小为止。

     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<map>
     7 #include<set>
     8 std::map<int,int>mp;
     9 std::set<int>b;
    10 int n,m,f[200005],g[200005],a[200005];
    11 int read(){
    12     char ch=getchar();int t=0,f=1;
    13     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    14     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
    15     return t*f;
    16 }
    17 int gcd(int a,int b){
    18     if (b==0) return a;
    19     else return gcd(b,a%b);
    20 }
    21 int F(int x){
    22     if (x<=1) return 0;
    23     if (b.count(x)) return -1;
    24     int rec=x,res=0;
    25     if (mp.find(rec)!=mp.end()) return mp[rec];
    26     int d=0,cnt=0;
    27     for (int i=2;i*i<=rec;i++){
    28         int p=i;
    29         if (x%p==0){
    30             if (b.count(p)) d=-1;else d=1;
    31             while (x%p==0) x/=p,cnt+=d;
    32         }
    33     }
    34     if (x!=1){
    35         if (b.count(x)) d=-1;else d=1;
    36         cnt+=d;
    37     }
    38     return (mp[rec]=cnt);
    39 }
    40 int main(){
    41     n=read();m=read();
    42     for (int i=1;i<=n;i++) a[i]=read();
    43     for (int i=1;i<=m;i++) {int x=read();b.insert(x);}
    44     int ans=0;
    45     g[1]=a[1];
    46     for (int i=2;i<=n;i++) g[i]=gcd(g[i-1],a[i]);
    47     for (int i=1;i<=n;i++) 
    48      ans+=F(a[i]);
    49     for (int i=n;i>=1;i--){
    50         int s=F(g[i]);
    51         if (s<0){
    52             ans-=s*i;
    53             int t=g[i];
    54             for (int j=1;j<=i;j++)
    55              g[j]/=t;
    56         }
    57     }
    58     printf("%d
    ",ans);
    59 }
  • 相关阅读:
    拷贝构造函数的参数为什么必须使用引用类型(避免无限递归拷贝,但其实编译器已经强制要求了)
    MAKE gnu
    设计模式之观察者模式(Observable与Observer)
    WCF从零学习之设计和实现服务协定2
    CLR_Via_C#学习笔记之枚举
    事件与动画
    Shell—学习之心得
    Asp.net MVC中提交集合对象,实现Model绑定
    一个23岁大学生的开源项目 谷歌要竖中指了
    C++中的虚函数总结
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5608412.html
Copyright © 2020-2023  润新知