P13863 [SWERC 2020] Decoration 题解
KobeBeanBryantCox · · 题解
P13863 [SWERC 2020] Decoration 题解
题目传送门。
线性时间线性空间做法。
截止至 2025-09-26,暂无题解,但是随机抽样翻看过题记录都是用倍增做的。
题意
构造长度为
无解输出
思路
注意到
容易发现如果确定了
考虑
原题目转化成在这个基环树森林上走长度为
考虑一条长度为
- 树上一个点到某个祖先的路径(这个点深度
\ge k )。 - 树上一个点到根,加上从根出发的环的某一段(这个点深度
<k )。
考虑对于每个点都算一遍从这个点开始的长度为
这个玩意倍增做完了。但是莫名多了一个老哥。
所以把环搞出来,做环的前缀和(可能需要破环成链)。
然后在 dfs 的过程中动态维护一个数组,表示当前点到根的路径的前缀和。
然后分类讨论上面两种情况就做完了。
时间复杂度
AC 代码
由于需要拓扑排序以及建反边之类的操作,常数略大。
::::success[code]
#include<bits/stdc++.h>
#define Code using
#define by namespace
#define wjb std
Code by wjb;
#define int long long
int in()
{
int k=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')k=k*10+c-'0',c=getchar();
return k*f;
}
void out(int x)
{
if(x<0)putchar('-'),x=-x;
if(x<10)putchar(x+'0');
else out(x/10),putchar(x%10+'0');
}
const int N=1e6+10;
int n,k;
vector<int>e[N];
int b[N],p[N],d[N],x[N];
void init(int n)
{
int tot=0;d[1]=1;
for(int i=2;i<=n;i++)
{
if(b[i]==0)d[i]=2,p[++tot]=i,x[i]=1;
for(int j=1;j<=tot&&i*p[j]<=n;j++)
{
b[i*p[j]]=1;
if(i%p[j]==0)d[i*p[j]]=d[i]/(x[i]+1)*(x[i]+2),x[i*p[j]]=x[i]+1;
if(i%p[j]==0)break;
x[i*p[j]]=1,d[i*p[j]]=d[i]*2;
}
}
}
int deg[N];bool isring[N];
void toposort()
{
queue<int>q;
for(int i=0;i<n;i++)isring[i]=1;
for(int i=0;i<n;i++)if(!deg[i])q.push(i);
while(!q.empty())
{
int u=q.front();q.pop(),isring[u]=0;
int v=(u+d[u])%n;
if(!--deg[v])q.push(v);
}
}
int vis[N];vector<int>s;
void dfs(int u)
{
vis[u]=1,s.push_back(u);
for(int v:e[u])if(!vis[v]&&isring[v])dfs(v);
}
int sum[N<<1];
int sumt[N],tot=0,len;
int minn=1e18,id=-1;
void solve(int u,int from)
{
tot++,sumt[tot]=sumt[tot-1]+u;
int val=1e18;
if(len+tot-1>=k)
if(tot>=k)val=sumt[tot]-sumt[tot-k];
else val=sumt[tot]+sum[from]-sum[from-(k-tot)];
if(val<minn)minn=val,id=u;
for(int v:e[u])if(!isring[v])solve(v,from);
sumt[tot--]=0;
}
void work()
{
len=s.size();
for(int i=1;i<=len;i++)sum[i]=sum[i-1]+s[i-1];
for(int i=len+1;i<=2*len;i++)sum[i]=sum[i-1]+s[i-len-1];
for(int i=len+1;i<=2*len;i++)tot=0,solve(s[i-len-1],i-1);
}
signed main()
{
n=in(),k=in(),init(n);
for(int i=0;i<n;i++)e[(i+d[i])%n].push_back(i),deg[(i+d[i])%n]++;
toposort();
for(int i=0;i<n;i++)if(!vis[i]&&isring[i])s.clear(),dfs(i),work();
if(id==-1)out(-1),exit(0);
for(int i=1;i<=k;i++)out(id),putchar(' '),id=(id+d[id])%n;
return 0;
}
::::