生活随笔
收集整理的這篇文章主要介紹了
codeforces1554 E. You(思维+数学+转化)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
E. You
首先我們假設每個節點有個點權,點權是兒子的數量。
一個點可以和他的父親所要權值1(先刪去自己,再刪去父親),并且此操作不可逆。于是dfs從葉子節點一次遞推即可得出某個kkk是否能作為gcd?\gcdgcd。
由于上述“權值交換”的過程只會變化1,并且權值和一定是n-1,只需要枚舉n-1的約數一一dfs遞推判斷即可。
注意:最后需要容斥一下重復計算的情況
upd:我們在dfs時并沒有直接考慮gcd?\gcdgcd,而是通過考慮點權是否是gcd?\gcdgcd的倍數,顯然如果一個是6的倍數,自然也是2的倍數,但gcd要求我們是最大公約數,所以由于2的答案是依附于6的基礎上,需要減去。
#include<bits/stdc++.h>
using namespace std
;
using ll
=long long;
template <class T=int> T
rd()
{T res
=0;T fg
=1;char ch
=getchar();while(!isdigit(ch
)) {if(ch
=='-') fg
=-1;ch
=getchar();}while( isdigit(ch
)) res
=(res
<<1)+(res
<<3)+(ch
^48),ch
=getchar();return res
*fg
;
}
const int N
=100010,mod
=998244353;vector
<int> g
[N
];
int a
[N
],n
;
ll ans
[N
];
bool dfs(int u
,int fa
,int val
)
{for(auto v
:g
[u
]){if(v
==fa
) continue;if(!dfs(v
,u
,val
)) return 0;}if(a
[u
]%val
==0){if(fa
) a
[fa
]++;return 1;}if((a
[u
]+1)%val
==0&&fa
) return 1;return 0;
}
void init()
{for(int i
=1;i
<=n
;i
++) ans
[i
]=0;for(int i
=1;i
<=n
;i
++) a
[i
]=0;for(int i
=1;i
<=n
;i
++) g
[i
].clear();
}
int main()
{int Tc
=rd();while(Tc
--){init();n
=rd();for(int i
=1;i
<n
;i
++){int u
=rd(),v
=rd();g
[u
].push_back(v
);g
[v
].push_back(u
);}for(int i
=1;i
<n
;i
++)if((n
-1)%i
==0){if(i
==1) {ans
[1]=1;for(int i
=1;i
<n
;i
++) ans
[1]=ans
[1]*2%mod
;continue;}for(int i
=1;i
<=n
;i
++) a
[i
]=0;if(dfs(1,0,i
)) ans
[i
]++;}for(int i
=n
;i
>=1;i
--)for(int j
=2;i
*j
<=n
;j
++)ans
[i
]=(ans
[i
]-ans
[i
*j
]+mod
)%mod
;for(int i
=1;i
<=n
;i
++) printf("%lld%c",ans
[i
]," \n"[i
==n
]);}return 0;
}
總結
以上是生活随笔為你收集整理的codeforces1554 E. You(思维+数学+转化)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。