题解:
本以为这道题是一个类似的之前做的一道斐波那契的\(DP\),一看数据范围就知道应该是乱搞差不离了\(,,,\)
我们预处理前\(45\)项\(Fibonacci\)数列,发现已经突破\(1e9\)了,于是我们直接每次询问扫一遍即可,时间复杂度\(O(T*45*45)\)
\(code\):
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<ctype.h>
#include<vector>
#include<queue>
#include<cstring>
#include<map>
#include<cmath>
#include<stdlib.h>
#include<ctime>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
#define mod 998244353
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
}
ll f[50],t,n;
int main()
{
read(t);
f[1]=f[2]=1;
for(int i=3;i<=46;i++) f[i]=f[i-1]+f[i-2];
while(t--)
{
bool flag=0;
read(n);
for(int i=0;i<=46;i++)
{
if(!flag)
for(int j=0;j<=46;j++)
{
if(f[i]*f[j]>n) break;
if(f[i]*f[j]==n) {flag=1;break;}
}
}
if(flag) puts("Yes");
else puts("No");
}
}
题解:
很显然,当两点之间的点数为奇数时,此时有解,否则显然无解,而有解时,显然我们应该去找中点;
我们对有解的情况分情况讨论:
\(1.dep[x]==dep[y]:\)
这时候只用将x、y上提到中点的前一个点就好,\(N-Sz[xx]-Sz[yy]\)即可;
\(2.dep[x]!=dep[y]:\)
我们假设\(dep[x]>dep[y]\),那么我们先找到他们的中点,再用中点的子树大小减去包含了\(x\)的子树的大小就行了;
\(code:\)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<ctype.h>
#include<vector>
#include<queue>
#include<cstring>
#include<map>
#include<cmath>
#include<stdlib.h>
#include<ctime>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
#define mod 998244353
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
}
const int maxn=100002;
int ans,n,log_[maxn],m;
int fa[maxn][20],dep[maxn],sz[maxn];
vector<int>G[maxn];
void dfs(int x,int pre)
{
fa[x][0]=pre;sz[x]++;
for(int i=1;i<=log_[n];i++)
if(fa[x][i-1]) fa[x][i]=fa[fa[x][i-1]][i-1];
else break;
for(int i=G[x].size()-1;i>=0;i--)
{
int p=G[x][i];
if(p==pre) continue;
dep[p]=dep[x]+1;
dfs(p,x);sz[x]+=sz[p];
}
}
int getlca(int x,int y)
{
if(x==y) return x;
if(dep[x]<dep[y]) swap(x,y);
int del=dep[x]-dep[y];
for(int i=log_[n];i>=0;i--)
if(del>>i&1) x=fa[x][i];
if(x==y) return x;
for(int i=log_[n];i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int moveup(int x,int k)
{
for(int i=log_[n];i>=0;i--)
if(k>>i&1) x=fa[x][i];
return x;
}
int main()
{
read(n);log_[0]=-1;
for(int i=1;i<=n;i++) log_[i]=log_[i>>1]+1;
for(int i=1;i<n;i++)
{
int x,y;
read(x),read(y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1,0);
read(m);
while(m--)
{
int x,y;
read(x),read(y);
if(x==y) {printf("%d\n",n);continue;}
int len=dep[x]+dep[y]-(dep[getlca(x,y)]<<1);
if(len&1) {puts("0");continue;}
if(dep[x]==dep[y])
{
int k=(len>>1)-1;
int xx=moveup(x,k);
int yy=moveup(y,k);
printf("%d\n",n-sz[xx]-sz[yy]);
}
if(dep[x]!=dep[y])
{
int k=(len>>1)-1;
if(dep[x]<dep[y]) swap(x,y);
int xx=moveup(x,k);
printf("%d\n",sz[fa[xx][0]]-sz[xx]);
}
}
}
题解:
贪心,显然两两相连接是最优的情况,如果不能满足就往里面加点,每加一次答案就多一条边;
\(code:\)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<ctype.h>
#include<vector>
#include<queue>
#include<cstring>
#include<map>
#include<cmath>
#include<stdlib.h>
#include<ctime>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
#define mod 998244353
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
}
const int maxn=100002;
int t,n,k,ans;
bool book[maxn];
vector<int>G[maxn];
void dfs(int x,int pre)
{
for(int i=G[x].size()-1;i>=0;i--)
{
int p=G[x][i];
if(p==pre) continue;
dfs(p,x);if(!book[p]&&!book[x])
ans++,book[x]=1;
}
}
int main()
{
read(t);
while(t--)
{
read(n),read(k);ans=0;
for(int i=1;i<=n;i++) G[i].clear(),book[i]=0;
for(int i=1;i<n;i++)
{
int x;
read(x);
G[x].push_back(i+1);
G[i+1].push_back(x);
// int y;
// read(x),read(y);
// G[x].push_back(y);
// G[y].push_back(x);
}
dfs(1,0);
if((ans<<1)>=k) printf("%d\n",(k>>1)+(k&1));
else printf("%d\n",k-ans);
}
}