Codeforces 809E:Surprise me! (모 비 우 스 재연 + 허수 수)
제목 분석: 극점 까지 의 틀 에 박 힌 문제.
공식 적 으로 유도 하여 직접 보다.https://blog.sengxian.com/solutions/cf-809e, QAQ 하기 귀찮아 요.
마지막 출시:
ans=∑T=1n∑d|Tdμ(Td)ϕ(d)∑d|ai∑d|ajϕ(ai)ϕ(aj)dis(i,j) a n s = ∑ T = 1 n ∑ d | T d μ ( T d ) ϕ ( d ) ∑ d | a i ∑ d | a j ϕ ( a i ) ϕ ( a j ) d i s ( i , j )
두 번 째 ∑ 뒤의 물건 을 G (T) G (T) 로 기록 하면 이것 은 O (nln (n) O (n ln (n)) 로 미리 처리 할 수 있다.그리고 모든 만족 d | ai d | a i 의 점 i 에 대해 허 수 를 만 들 고 허 수 중의 임의의 한 변 을 매 거 하 며 이 변 의 길이 로 좌우 양쪽 을 곱 합 니 다.ϕ ϕ 공헌 할 가치 가 있 는 답안.a 는 1 ~ n 의 한 배열 이기 때문에 허수 의 총 크기 는 nln (n) n ln (n) 이다.ST 표 로 예비 처 리 를 하면 O (1) O (1) 가 LCA 를 구 할 수 있다.모든 조건 을 만족 시 키 는 점 i 를 시간 스탬프 에 따라 정렬 하면 시간 복잡 도 여러 log log.처음에는 모든 점 을 정렬 한 다음 순서대로 vector 에 삽입 할 수 있 습 니 다.매 거 인 수 를 해 야 하기 때문에 시간 은 ∑ ni = 1i √ ∑ i = 1n i 이 고 대략 6 ∗ 107 6 ∗ 10.7 이다.
처음에는 허수아비 의 변 권 이 1 (naive!) 인 줄 알 고 WA 가 한 번 했다.나중에 RE 가 되 었 습 니 다. 저 는 vector 의 문제 인 줄 알 았 습 니 다.
그래서 제 가 이 문 제 를 푸 는 것 은 바로 허 수 를 쓰 는 연습 을 하기 위해 서 입 니 다. 이것 은 아마 마지막 허 수 문제 일 것 입 니 다.
그리고 나 서 나 는 코드 에 있 는 빈 나무의 템 플 릿 을 뽑 았 다.
tail=1;
sak[1]=tree[1];
for (int i=2; i<=Node[d].size(); i++)
{
int x=tree[i],last=0,p=Lca(sak[tail],x);
while ( dep[ sak[tail] ]>dep[p] && tail ) last=sak[tail--];
if (sak[tail]!=p) Fa[p]=sak[tail],sak[++tail]=tree[++cnt]=p;
if (last) Fa[last]=p;
Fa[x]=p;
sak[++tail]=x; //!!!
}
int root=sak[1];
Fa[root]=0;
이 코드 는 자신 이 가상 나무 에 대한 이해 YY 에 따라 나 온 것 이기 때문에 매우 간단 하 다 (chou) 결 (lou). 순 전 히 자신 에 게 시간 이 있 을 때 보 여 주 는 것 이 고 뿌리 는 것 을 좋아 하지 않 는 다.
이 문 제 는 원래 1h 를 계획 한 것 이 었 는데 1h 때 코드 를 다 쳤 고 25min 이 지나 서 야 조정 되 었 으 며 코드 능력 은 강화 해 야 한다.
CODE:
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=200100;
const int maxl=20;
const long long M=1000000007;
typedef long long LL;
struct edge
{
int obj;
edge *Next;
} e[maxn<<1];
edge *head[maxn];
int cur=0;
vector <int> Node[maxn];
int Rank[maxn];
int dep[maxn];
int dfn[maxn];
int Time=0;
int Lg[maxn<<1];
int dfsx[maxn<<1];
int ST[maxn<<1][maxl];
int tree[maxn];
int cnt;
int sak[maxn];
int tail;
LL Size[maxn];
int Fa[maxn];
int phi[maxn];
int miu[maxn];
LL rev[maxn];
LL G[maxn];
bool vis[maxn];
int prime[maxn];
int num=0;
int a[maxn];
int n;
LL ans=0;
void Add(int x,int y)
{
cur++;
e[cur].obj=y;
e[cur].Next=head[x];
head[x]=e+cur;
}
void Linear_shaker()
{
phi[1]=miu[1]=1;
for (int i=2; i<=n; i++)
{
if (!vis[i]) phi[i]=i-1,miu[i]=-1,prime[++num]=i;
for (int j=1; j<=num && i*prime[j]<=n; j++)
{
int k=i*prime[j];
vis[k]=true;
if (i%prime[j])
{
phi[k]=phi[i]*(prime[j]-1);
miu[k]=-miu[i];
}
else
{
phi[k]=phi[i]*prime[j];
miu[k]=0;
break;
}
}
}
rev[1]=1;
for (LL i=2; i<=n; i++)
{
LL x=M/i,y=M%i;
rev[i]=x*rev[y]%M;
rev[i]=M-rev[i];
}
for (int i=1; i<=n; i++) if (miu[i]==-1) miu[i]=M-1;
for (int i=1; i<=n; i++)
for (int j=1; i*j<=n; j++)
G[i*j]=(G[i*j]+ (long long)i*miu[j]%M*rev[ phi[i] ]%M )%M;
}
void Dfs(int node,int fa)
{
dfn[node]=++Time;
dfsx[Time]=node;
for (edge *p=head[node]; p; p=p->Next)
{
int son=p->obj;
if (son==fa) continue;
dep[son]=dep[node]+1;
Dfs(son,node);
dfsx[++Time]=node;
}
}
bool Comp(int x,int y)
{
return dfn[x]int Lca(int x,int y)
{
x=dfn[x],y=dfn[y];
if (x>y) swap(x,y);
int lg=Lg[y-x];
y=y-(1<1;
x=ST[x][lg];
y=ST[y][lg];
if (dep[x]return x;
return y;
}
void Calc(int node)
{
for (edge *p=head[node]; p; p=p->Next)
{
int son=p->obj;
Calc(son);
Size[node]=(Size[node]+Size[son])%M;
}
}
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%d",&n);
for (int i=1; i<=n; i++) scanf("%d",&a[i]),head[i]=NULL;
for (int i=1; iint x,y;
scanf("%d%d",&x,&y);
Add(x,y);
Add(y,x);
}
Linear_shaker();
dep[1]=1;
Dfs(1,1);
for (int i=1; i<=Time; i++) ST[i][0]=dfsx[i];
for (int j=1; jfor (int i=1; i<=Time; i++)
{
int mid=min(i+(1<1)),Time);
if (dep[ ST[i][j-1] ]1] ]) ST[i][j]=ST[i][j-1];
else ST[i][j]=ST[mid][j-1];
}
Lg[1]=0;
for (int i=2; i<=Time; i++) Lg[i]=Lg[i>>1]+1;
for (int i=1; i<=n; i++) Rank[i]=i;
sort(Rank+1,Rank+n+1,Comp);
for (int i=1; i<=n; i++)
{
int node=Rank[i];
int max_d=(int)floor( sqrt( (double)a[node] )+0.001 );
for (int d=1; d<=max_d; d++)
if (a[node]%d==0)
{
Node[d].push_back(node);
if (d!=a[node]/d) Node[ a[node]/d ].push_back(node);
}
}
for (int d=1; d<=n; d++)
{
cnt=0;
for (int i=0; i1;
sak[1]=tree[1];
for (int i=2; i<=Node[d].size(); i++)
{
int x=tree[i],last=0,p=Lca(sak[tail],x);
while ( dep[ sak[tail] ]>dep[p] && tail ) last=sak[tail--];
if (sak[tail]!=p) Fa[p]=sak[tail],sak[++tail]=tree[++cnt]=p;
if (last) Fa[last]=p;
Fa[x]=p;
sak[++tail]=x; //!!!
}
int root=sak[1];
Fa[root]=0;
cur=0;
for (int i=1; i<=cnt; i++) head[ tree[i] ]=NULL;
for (int i=1; i<=cnt; i++)
{
int x=tree[i];
if (Fa[x]) Add(Fa[x],x);
if (i<=Node[d].size()) Size[x]=phi[ a[x] ];
else Size[x]=0;
}
Calc(root);
LL tot=Size[root],temp=0;
for (int i=1; i<=cnt; i++)
{
int x=tree[i];
if (x==root) continue;
temp=(temp+ Size[x]*(tot-Size[x]+M)%M*(dep[x]-dep[ Fa[x] ])%M )%M; //!!!
}
temp=temp*G[d]%M;
ans=(ans+temp)%M;
}
ans=ans*rev[n]%M;
ans=ans*rev[n-1]%M;
ans=ans*2LL%M;
printf("%I64d
",ans);
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Iterated Linear Function 매트릭스 빠른 멱Consider a linear function f(x) = Ax + B. Let’s define g(0)(x) = x and g(n)(x) = f(g(n - 1)(x)) for n > 0. For the given...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.