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 }