Agc003_E Sequential operations on Sequence
Posted oyjason
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Agc003_E Sequential operations on Sequence相关的知识,希望对你有一定的参考价值。
题目大意
$1,2...n,n$个数从小到大排列,有$m$此操作,每次操作给定一个参数$x$,将当且数列作为循环节无限地展开下去,再取前$x$个作为新的数列,求最终的数列每个数出现的次数。
$n,mleq 10^5,xleq 10^{18}$
题解
人类智慧题
首先对于两个$x$不递增的连续操作,上一次操作是没有意义的,对于第一次操作$x<n$,要特判出来。
记当前数列长度为$len$,新家入的操作是$x$,先算出$x$中有多少个$len$,就知道最终答案会由多少个$len$代表的数列构成。由于每一步操作留下的数列一定会作为循环节的前缀出现在新数列中,我们将$xmod len$的值计算出来,再递归找到最后一个操作使得该操作结束后$len<x$,递归处理即可,直到$xleq n$,这样就将$1-x$的数依次加入最终答案即可。
考虑从最后一个操作向前递推,不断求出形如$1-x$独立出现了多少次,最终统计答案即可。
由于对于每一步操作,每一次查找$len$出现的位置需要二分,每次$x$由于取模的缘故会至少变为原来的一半,所以是查找不会超过$log x$次,复杂度为$O(mlog mlog x+n)$。
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define M 100020 using namespace std; const int BS=1<<19;char BF[BS],OT[BS],*SZ=OT,*HD,*TL; const char *ED=OT+BS-1; char SS[20]; int Top; char Getchar(){if(HD==TL) TL=(HD=BF)+fread(BF,1,BS,stdin);return *HD++;} void flush(){fwrite(OT,1,SZ-OT,stdout);} void Putchar(char c){*SZ++ =c;if(SZ==ED) flush(),SZ=OT;} void write(LL x){ if(!x){Putchar(x),Putchar(‘ ‘);} while(x) SS[++Top]=(x%10+‘0‘),x/=10; while(Top) Putchar(SS[Top]),Top--; Putchar(‘ ‘); } LL read(){ LL nm=0,fh=1; char cw=Getchar(); for(;!isdigit(cw);cw=Getchar()) if(cw==‘-‘) fh=-fh; for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-‘0‘); return nm*fh; } LL n,T,m,p[M],N,G[M],F[M],K[M],tmp; int main(){ n=read(),T=read(); while(T--){LL x=read(); while(m&&p[m]>=x) m--; p[++m]=x;} if(m&&p[1]<n){N=n,n=p[1];for(LL i=1;i<m;i++) p[i]=p[i+1];m--;} G[0]=p[0]=n,F[m]=1; for(LL i=m;i>=0;i--){ LL res=p[i],now=i-1; while(res>n){ LL k=res/p[now]; F[now]+=F[i]*k,res-=k*p[now]; now=upper_bound(p,p+now,res)-p-1; } G[i]=res,K[1]+=F[i],K[G[i]+1]-=F[i]; } for(LL i=1;i<=n;i++) K[i]+=K[i-1],write(K[i]); while(n<N) n++,Putchar(‘0‘),Putchar(‘ ‘); flush(); return 0; }
以上是关于Agc003_E Sequential operations on Sequence的主要内容,如果未能解决你的问题,请参考以下文章
agc003E Sequential operations on Sequence
[AGC003]F - Fraction of Fractal