A meeting
答案为最远关键点的距离的一半向上取整,也就是关键点的树的直径的一半向上取整。
先考虑两个点,他俩是最远距离,那么最短时间就是⌈d/2⌉,在此基础上再加一个点(前提是加上这个点,后不影响初始条件,即初始的两个点之间的距离最远),那么不会影响答案,因为他与另外两个点的相会的时间必然小于⌈d/2⌉,这个题是最小化最大值。
所以答案是关键点的树的直径的一半向上取整.
求树的直径的方法有两半BFS,两边DFS,书上DP。
另附两遍BFS的代码:
#include
#define inf 0x3f3f3f3f
#define Pair pair
#define int long long
#define fir first
#define sec second
namespace IO {
const int maxn=14096;char buf[maxn],t[50];int bn=maxn,bi=maxn;
int read(char* s) {
while(bn){for(;bi' ';bi++)s[sn++]=buf[bi];if (biq;
q.push(u);use[u]=1;
while(q.size()){
int wide=q.size();num++;
while(wide--){
int x=q.front();q.pop();
for(int i=head[x];~i;i=Next[i]){
int y=ver[i];
if(use[y]) continue;q.push(y);
if(co[y]){R=num;last=y;}
use[y]=1;
}
}
}
return last;
}
signed main(){
;;;;;;;;;;;;;;;;;;;;;;;
int n,k;read(n);read(k);
for(int i=0;i
D triples I:
基本是官方题解,我进行简单的举例。
首先我们知道每一个二进制位mod3只有1或者2两种情况,我们简单举个例子:
8 4 2 1 mod3 分别为2 1 2 1
前若干位512 256 128 64 32 16 8 4 2 1
模数: 2 1 2 1 2 1 2 1 2 1
如果a是3的倍数,那么我们直接输出a,不然结果必为两个数相或为结果
如果a的二进制只有一位或两位,不存在两个3的倍数或之后结果为a。
接下来考虑a至少有三位的情况。
若a mod 3=1:
•如果a中的二进制位有至少两个mod 3=1的,设它们为p和q,我们取{a-p,a-q}即可。
加入a为13 (8+4+1) 对应模数为(2+1 +1),多出来的1导致了结果mod 3=1,我们用a减去这个1就是3的倍数,此时这个3的倍数的被减去的二进制位为0,可以通过减去另一个1,产生的另一个3的倍数,两者相或可以弥补二进制位置。
• 如果a中的二进制位有恰好一个mod 3=1的,那么设mod 3=1的这个位为p,mod 3=2 的某个位为q,我们取{a-p,p+q}即可。
如a= 43 (32+8+2+1)对应模数为(2+2+2 +1),多出来的1导致了结果mod 3=1,剪掉这个 1,则产生第一个3的倍数,这个1随便加上一个2,也是3的倍数,同时可相互弥补二进制中的位数,
• 如果a中的二进制位没有mod 3=1的,那么假设有三个mod 3=2的位p,q,r,我们取{a-p-q,p+q+r}即可。
如a= 682 (512+128+32+8+2)对应模数为(2+2+2 +2+2),多出来的4导致了结果mod 3=1,剪掉这个 2+2,则产生第一个3的倍数,这两个2随便加上一个2,也是3的倍数,同时可相互弥补二进制中的位数,
• 若a mod 3=2只需把上面的讨论中1与2互换即可,是完全对称的。
我们简单分别举一下例子:
至少两个mod 3=2:
如a= 14 (8+4+2)对应模数为(2+1 +2),多出来的2导致了结果mod 3=2,剪掉这个2,则产生第一个3的倍数,这个2随便加上一个1,也是3的倍数,同时可相互弥补二进制中的位数,
恰好一个mod 3=2的:
如a= 85 (64+16+4+1)对应模数为(1+1+1 +2),多出来的2导致了结果mod 3=2(也可理解为多出来的1+1 导致mod3=2),剪掉这个2,则产生第一个3的倍数,这个2随便加上一个1,也是3的倍数,同时可相互弥补二进制中的位数,
没有mod 3=1的:
如a= 85 (64+16+4+1)对应模数为(1+1+1 +1+1),多出来的1+1导致了结果mod 3=2,剪掉这个(1+1),则产生第一个3的倍数,这两个1随便加上一个1,也是3的倍数,同时可相互弥补二进制中的位数,
另附代码:
#include
#define inf 0x3f3f3f3f
#define Pair pair
#define int long long
#define fir first
#define sec second
namespace IO {
const int maxn=14096;char buf[maxn], t[50];int bn=maxn,bi=maxn;
int read(char* s) {
while(bn){for(;bi' ';bi++)s[sn++]=buf[bi];if(bione,two;
void f(int x){
one.clear();two.clear();
int base=1;
while(x){
if(x&1){
if(base%3==1)one.push_back(base);
else two.push_back(base);
}
base*=2;
x>>=1;
}
}
signed main(){
int t;cin>>t;
while(t--){
int n;cin>>n;f(n);
if(n%3==0)printf("%lld %lld\n",1,n);
else{
if(n%3==1){
if(one.size()>=2)printf("%lld %lld %lld\n",2,n-one[0],n-one[1]);
else{
if(one.size()==1)printf("%lld %lld %lld\n",2,n-one[0],one[0]+two[0]);
else printf("%lld %lld %lld\n",2,n-two[0]-two[1],two[0]+two[1]+two[2]);
}
}else{
if(two.size()>=2)printf("%lld %lld %lld\n",2,n-two[0],n-two[1]);
else{
if(two.size()==1)printf("%lld %lld %lld\n",2,n-two[0],one[0]+two[0]);
else printf("%lld %lld %lld\n",2,n-one[0]-one[1],one[0]+one[1]+one[2]);
}
}
}
}
return 0;
}
K number
后缀和找规律,
简单附代码
#include
#define inf 0x3f3f3f3f
#define Pair pair
#define int long long
#define fir first
#define sec second
namespace IO {
const int maxn=14096;char buf[maxn], t[50];int bn=maxn,bi=maxn;
int read(char* s) {
while(bn){for(;bi' ';bi++)s[sn++]=buf[bi];if(bi=1;i--)num[i]=num[i]+num[i+1];
int z=0,res=0;
for(int i=1;i<=len;i++){
if(str[i]=='0')z++;
else{
res+=(1+z)*z/2;z=0;
}
}
if(z)res+=(1+z)*z/2;z=0;
//printf("%lld\n",res);
for(int i=len;i>=1;i--){
if(str[i]=='0'){
z++;
//cout<=2)m[num[i+1]%3]+=z-1;
z=0;
}
res+=m[num[i]%3];
}
printf("%lld\n",res);
return 0;
}