A. Robbers’ watch
由于两个数位数加起来不能超过7,枚举可能出现的数,暴力统计,有一些小坑要细心。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll change(ll x){
ll res = 0;
ll bit = 1;
while(x){
res += (x%7)*bit;
x /= 7;
bit *= 10;
}
return res;
}
int fa[] = {1,1,2,6,24,120,720,5040,40320};
int C(int n,int k){
return fa[n]/fa[k]/fa[n-k];
}
ll len(int x){
int res = 0;
while(x){
x /= 10;
res++;
}
return max(res,1);
}
bool check(int x,int len){
bool vis[11];
for(int i=0;i<7;i++){
vis[i] = 0;
}
while(len--){
if(x%10 > 6){
return 0;
}
int cur = x%10;
if(vis[cur]){
return 0;
}
vis[cur] = 1;
x /= 10;
}
return 1;
}
int num_n[5555];
int num_m[5555];
int cntn = 0;
int cntm = 0;
int lenn;
int lenm;
bool judge(int x,int lenx,int y,int leny){
bool vis[11];
for(int i=0;i<7;i++){
vis[i] = 0;
}
while(lenx--){
int cur = x%10;
if(vis[cur]){
return 0;
}
vis[cur] = 1;
x /= 10;
}
while(leny--){
int cur = y%10;
if(vis[cur]){
return 0;
}
vis[cur] = 1;
y /= 10;
}
return 1;
}
int main(){
ll n,m;
cin>>n>>m;
if(n==1 && m==1){
cout<<0<<endl;
return 0;
}
n--;
m--;
ll nn = change(n);
ll mm = change(m);
lenn = len(nn);
lenm = len(mm);
if(lenn + lenm >7){
cout<<0<<endl;
return 0;
}
for(int i=0;i<=nn;i++){
if(check(i,lenn)){
num_n[cntn++] = i;
}
}
for(int i=0;i<=mm;i++){
if(check(i,lenm)){
num_m[cntm++] = i;
}
}
int ans = 0;
for(int i=0;i<cntn;i++){
for(int j=0;j<cntm;j++){
int ii = num_n[i];
int jj = num_m[j];
if(judge(ii,lenn,jj,lenm)){
ans++;
}
}
}
cout<<ans<<endl;
return 0;
}
B. Kay and Snowflake
参考倍增法求LCA,找出每个节点 size 最大的儿子作为大儿子,倍增儿子寻找答案。即往最大的后代方向找,直到找到第一个最大后代不会过大为止。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 300010;
vector<int> G[maxn];
int maxSon[maxn];
int size[maxn];
void dfs(int u){
int sz = G[u].size();
size[u] = 1;
for(int i=0;i<sz;i++){
int v = G[u][i];
dfs(v);
size[u] += size[v];
maxSon[u] = max(maxSon[u],size[v]);
}
}
int n,q;
int bestSon[maxn][22];
int main(){
cin>>n>>q;
for(int i=2;i<=n;i++){
int pp;
scanf("%d",&pp);
G[pp].push_back(i);
}
dfs(1);
for(int i=1;i<=n;i++){
int sz = G[i].size();
for(int j=0;j<sz;j++){
int v = G[i][j];
if(size[v]>size[bestSon[i][0]]){
bestSon[i][0] = v;
}
}
}
for(int i=1;i<=20;i++){
for(int j=1;j<=n;j++){
bestSon[j][i] = bestSon[ bestSon[j][i-1] ][i-1] ;
}
}
while(q--){
int u;
scanf("%d",&u);
if(maxSon[u]*2<=size[u]){
printf("%d\n",u);
continue;
}
int ans = u;
for(int i=0;i<20;i++){
int v = bestSon[ans][i];
if(maxSon[v]*2<=size[u]){
if(i==0){
ans = v;
break;
}
ans = bestSon[ans][i-1];
i = -1;
continue;
}
}
printf("%d\n",ans);
}
return 0;
}