【CF402D】Upgrading Array(素数+质因数+gcd+贪心)

it2022-05-05  106

不难发现 题目中给出的f函数 其实就是一个数分解质因数后好素数和坏素数的个数之差

也就是说 数x带来的贡献 与x的质因数的种类有关系 又联想到gcd[1~x]一定是这个数的因子 也就是说一个数的贡献可以表示成:f(gcd[1~x])+f(....)

容易想到贪心做法:我们从后往前枚举 如果当前gcd前缀带来的贡献<0 就除一下

另外有几个小细节我平时没有注意到的: 1.线性筛素数 其实枚举范围只需要到区间根号范围就行 如果要用到特别大的那几个素数只需特判就行(46行) 2.map和bitset屌爆了

#include<bits/stdc++.h> #define N 2000005 #define MAX 5000000 #define int long long using namespace std; template<class T> inline void read(T &x) { x=0; static char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); } int n,m,a[N],gcd[N]; int prime[MAX+5],cnt,isprime[MAX+5]; bitset<1000000005> bad; inline int calcgcd(int a,int b) { return b? calcgcd(b,a%b):a; } void GetPrime() { isprime[0]=isprime[1]=1; for(register int i=2;i<=MAX;i++) { if(!isprime[i]) prime[++cnt]=i; for(register int j=1;j<=cnt&&i*prime[j]<=MAX;j++) { isprime[i*prime[j]]=1; if(i%prime[j]==0) break; } } } inline int calc(int x) { if(x==1) return 0; int sum=0; for(int i=1;i<=cnt&&prime[i]*prime[i]<=x;i++) { while(x%prime[i]==0) { sum+=(bad[prime[i]]?-1:1); x/=prime[i]; } } if(x!=1) sum+=(bad[x]?-1:1); return sum; } main() { read(n); read(m); for(int i=1;i<=n;i++) read(a[i]),gcd[i]=calcgcd(a[i],gcd[i-1]); GetPrime(); for(int i=1,x;i<=m;i++) read(x),bad[x]=true; int ans=0,tag=1; for(int i=1;i<=n;i++) ans+=calc(a[i]); for(int i=n;i>=1;i--) { gcd[i]/=tag; int tmp=calc(gcd[i]); if(tmp<0) { ans-=tmp*i; tag*=gcd[i]; } } cout<<ans<<endl; return 0; }

转载于:https://www.cnblogs.com/Patrickpwq/articles/9863591.html

相关资源:各显卡算力对照表!

最新回复(0)