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\n",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\n",ans);
59 }

 

posted @ 2016-06-22 20:28  GFY  阅读(464)  评论(0编辑  收藏  举报