1. 程式人生 > >2018.10.24 練習賽

2018.10.24 練習賽

ref ron 每次 using span detail 復雜 找到 long

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

2018.10.24 練習賽