D-子树的大小_牛客小白月赛62 (nowcoder.com)
题意:
思路:
本来应该是树形DP板子题,但是看到数据范围1e16,显然不能直接枚举
看到类似于1e18,1e16的数据范围,应当想到:
1.更换枚举对象
2.打表找规律
3.Log做法
考虑到这是一棵k叉树,树的形状非常规律,我们可以一层一层地遍历,计算贡献即可
一开始 l 和 r集中在结点x上,往下遍历的时候:l=k*l+1,r=k*r+k,直到不能往下走为止
每一层的贡献是 r-l+1
对于最后一层,贡献应当是 n-l
Code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mxn=3e5+10;
int n,k,m,ans=0;
int q[mxn];
void solve(){
ans=0;
cin>>n>>k>>m;
for(int i=1;i<=m;i++) cin>>q[i];
for(int i=1;i<=m;i++){
ans=0;
if(k==1) cout<<n-q[i]<<'\n';
else{
int l,r;
l=r=q[i];
while(l<n){
if(r<n){
ans+=(r-l+1);
}else{
ans+=n-l;
break;
}
l=k*l+1;
r=k*r+k;
}
cout<<ans<<'\n';
}
}
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T;
cin>>T;
while(T--)solve();
return 0;
}
总结:
一、
看到类似于1e18,1e16的数据范围,应当想到:
1.更换枚举对象
2.打表找规律
3.Log做法
二、
对于规则的树的形状,我们可以找规律计算其贡献