BZOJ2790 [Poi2012]Distance

来源:互联网 发布:软媒魔方怎么优化图标 编辑:程序博客网 时间:2024/06/12 18:55

一个数x可以分解为∏p[i]^a[i],设g[x]为把x分解后的sigma a[i],则x与y的距离为g[x]+g[y]-2*g[gcd(x,y)]

用f[i]表示他给你的数中,是i的倍数的数的g的最小值,f1[i]表示次小值,n根号max(a[i])算出f值之后对每个a[i]根号枚举约数算答案即可

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<vector>#include<map>#include<set>#include<bitset>#include<queue>#include<stack>using namespace std;#define MAXN 100010#define MAXM 1010#define MAXP 1000010#define INF 1000000000#define MOD 1000000007#define eps 1e-8#define ll long longint f[MAXP],f1[MAXP];int a[MAXN];int n;bool np[MAXP];int p[MAXP],g[MAXP],tot;int ansv[MAXN],ans[MAXN];void su(){int i,j;for(i=2;i<MAXP;i++){if(!np[i]){p[++tot]=i;g[i]=1;}for(j=1;j<=tot&&(ll)p[j]*i<MAXP;j++){np[p[j]*i]=1;g[p[j]*i]=g[i]+1;if(!(i%p[j])){break;}}}}int main(){int i,j;su();scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&a[i]);} memset(ansv,0x3f,sizeof(ansv));g[0]=MAXP;for(i=1;i<=n;i++){for(j=1;j*j<=a[i];j++){if(!(a[i]%j)){if(g[a[i]]<g[a[f[j]]]){f1[j]=f[j];f[j]=i;}else if(g[a[i]]<g[a[f1[j]]]){f1[j]=i;}if(j*j!=a[i]){if(g[a[i]]<g[a[f[a[i]/j]]]){f1[a[i]/j]=f[a[i]/j];f[a[i]/j]=i;}else if(g[a[i]]<g[a[f1[a[i]/j]]]){f1[a[i]/j]=i;}}}}}for(i=1;i<=n;i++){for(j=1;j*j<=a[i];j++){if(!(a[i]%j)){int t=f[j];if(f[j]==i){t=f1[j];}int tv=g[a[i]]+g[a[t]]-2*g[j];if(tv<ansv[i]){ansv[i]=tv;ans[i]=t;}else if(tv==ansv[i]&&t<ans[i]){ans[i]=t;}if(j*j!=a[i]){t=f[a[i]/j];if(f[a[i]/j]==i){t=f1[a[i]/j];}tv=g[a[i]]+g[a[t]]-2*g[a[i]/j];if(tv<ansv[i]){ansv[i]=tv;ans[i]=t;}else if(tv==ansv[i]&&t<ans[i]){ans[i]=t;}}}}}for(i=1;i<=n;i++){printf("%d\n",ans[i]);}return 0;}/*310 2 9 */


0 0
原创粉丝点击