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]:\)

这时候只用找到这两个节点中点的儿子中包含这两个点就的节点(写得有点绕,意会意会),\(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);
    }
}

猜你喜欢

转载自www.cnblogs.com/KatouKatou/p/9846452.html