2018.10.24 练习赛

T1 【NOIP2017模拟】Fibonacci

题解:

本以为这道题是一个类似的之前做的一道斐波那契的\(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");
	}
}

T2【NOIP2017模拟】一样远

题解:

很显然,当两点之间的点数为奇数时,此时有解,否则显然无解,而有解时,显然我们应该去找中点;

我们对有解的情况分情况讨论:

\(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]);
		}
	}
}

T3 【NOIP2017模拟】拆网线

题解:

贪心,显然两两相连接是最优的情况,如果不能满足就往里面加点,每加一次答案就多一条边;

\(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);
	}
}

posted @ 2018-10-24 21:52  Katoumegumi  阅读(74)  评论(0编辑  收藏  举报
返回顶部