P8155 「PMOI-5」公约数变换
Link_Cut_qwq · · 题解
传送门
在开始前我们先思考一个简化版:
其实复杂度是不到的。因为里面大多数的数都没有
代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define N 100010
using namespace std;
ull n,m,a[N],f[2][65][65],t[2][65],cnt[2],c[2][65],ans;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%llu",&a[i]);
ull x=2;
while(m>1)
{
if(m%x==0)
m/=x,f[0][1][++c[0][1]]=x,x=1;
x++;if(x*x>m) break;
}
if(m!=1) f[0][1][++c[0][1]]=m;
t[0][2]=8e18;cnt[0]=1;
ull now,cur;bool u;
for(int i=1;i<=n;i++)
{
u^=1;cur=a[i];cnt[u]=0;now=0;
memset(f[u],0,sizeof(f[u]));
memset(c[u],0,sizeof(c[u]));
for(int j=1;j<=cnt[u^1];j++)
{
cur+=(t[u^1][j]-now);now=t[u^1][j];
ull p=t[u^1][j+1],w[60];int c1,nd;
while(true)
{
c1=1;nd=0;
for(int k=1;k<=c[u^1][j];k++)
if(f[u^1][j][k]!=f[u][cnt[u]][c1])
w[++nd]=f[u^1][j][k];
else c1++;
ull mi=8e18,q=-1;
for(int k=1;k<=nd;k++)
if(((cur-1)/w[k]+1)*w[k]-cur<=p-now)
if(((cur-1)/w[k]+1)*w[k]-cur<mi)
mi=((cur-1)/w[k]+1)*w[k]-cur,q=w[k];
if(q==-1) break;
now+=((cur-1)/q+1)*q-cur;cur=(cur-1)/q+1;
cnt[u]++;
for(int k=1;k<=c[u][cnt[u]-1];k++)
f[u][cnt[u]][k]=f[u][cnt[u]-1][k];
c[u][cnt[u]]=c[u][cnt[u]-1];
f[u][cnt[u]][++c[u][cnt[u]]]=q;
int s=c[u][cnt[u]];
while(s>1&&f[u][cnt[u]][s]<f[u][cnt[u]][s-1])
swap(f[u][cnt[u]][s],f[u][cnt[u]][s-1]),s--;
t[u][cnt[u]]=now;
}
}
ans=max(ans,now);t[u][cnt[u]+1]=8e18;
}
cout<<ans<<endl;
return 0;
}