人生如此复杂,机会多得像稠密图,我们没理由认输。尽管我们走不了最短路,但图仍是连通图。TLE之前,没有一个节点叫失败。(You know what's cooking? BOOM~~)!

CCF 全国信息学奥林匹克联赛复赛模拟

CCF 全国信息学奥林匹克联赛复赛模拟

提高组
08:30~12:00
(请选手务必仔细阅读本页内容)
一.题目概况

fib equal tree
fib equal tree
fib.in equal.in tree.in
fib.out equal.out tree.out
1 秒 1 秒 1 秒
20 20 20
5 5 5

全文比较(过滤行末空格及文末回车)
传统 传统 传统
64M 64M 64M


二.提交源程序文件名

fib.c equal.c tree.c
fib.pas equal.pas tree.pas


三. 编译命令(不包含任何优化开关)

gcc -o fib
fib.c -lm
gcc -o equal
equal.c -lm
gcc -o tree
tree.c -lm
fpc fib.pas fpc equal.pas fpc tree.pas


四、 注意事项:
1、文件名(程序名和输入输出文件名) 必须使用英文小写。
2、 C/C++中函数 main()的返回值类型必须是 int, 程序正常结束时的返回值必须是 0。
3、全国统一评测时采用的机器配置为: CPU Intel® Pentium® Processor E6700, 3.2GHz,
内存 4G, 上述时限以此配置为准。
4、只提供 Linux 格式附加样例文件。
5、特别提醒: 评测在最新公布的 NOI Linux 下进行, 各语言的编译器版本以其为准。

1、 Fibonacci(fib.pas/cpp)

【问题描述】
豆豆最近迷上了 Fibonacci 数,然后他开始研究 Fibonacci 数的乘积。现在他想问你某
个数能不能分解成两个 Fibonacci 数的乘积?
Fibonacci 数的定义: F0=0,F1=1,Fk=Fk-1+Fk-2
【输入格式】
第一行一个整数 T 代表提问次数。
接下来 T 行,每行一个数字 A 表示豆豆询问你的数。
【输出格式】
对于每次提问,如果这个数可以被分解成两个 Fibonacci 数的成绩输出“Yes”,否则输
出“No”。
【输入样例】
5 5 4
12
11
10
【输出样例】
Yes
Yes
No
No
Yes
【数据范围】
对于 50%的数据: A≤50;
对于 100%的数据: T≤100, 0≤A≤109

打表,不解释

1.

//
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
int ans[5000]={1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,63245986,102334155,165580141,267914296,433494437,701408733,0,0,2,4,6,10,16,26,42,68,110,178,288,466,754,1220,1974,3194,5168,8362,13530,21892,35422,57314,92736,150050,242786,392836,635622,1028458,1664080,2692538,4356618,7049156,11405774,18454930,29860704,48315634,78176338,126491972,204668310,331160282,535828592,866988874,0,0,3,6,9,15,24,39,63,102,165,267,432,699,1131,1830,2961,4791,7752,12543,20295,32838,53133,85971,139104,225075,364179,589254,953433,1542687,2496120,4038807,6534927,10573734,17108661,27682395,44791056,72473451,117264507,189737958,307002465,496740423,803742888,0,0,5,10,15,25,40,65,105,170,275,445,720,1165,1885,3050,4935,7985,12920,20905,33825,54730,88555,143285,231840,375125,606965,982090,1589055,2571145,4160200,6731345,10891545,17622890,28514435,46137325,74651760,120789085,195440845,316229930,511670775,827900705,0,0,8,16,24,40,64,104,168,272,440,712,1152,1864,3016,4880,7896,12776,20672,33448,54120,87568,141688,229256,370944,600200,971144,1571344,2542488,4113832,6656320,10770152,17426472,28196624,45623096,73819720,119442816,193262536,312705352,505967888,818673240,0,0,13,26,39,65,104,169,273,442,715,1157,1872,3029,4901,7930,12831,20761,33592,54353,87945,142298,230243,372541,602784,975325,1578109,2553434,4131543,6684977,10816520,17501497,28318017,45819514,74137531,119957045,194094576,314051621,508146197,822197818,0,0,21,42,63,105,168,273,441,714,1155,1869,3024,4893,7917,12810,20727,33537,54264,87801,142065,229866,371931,601797,973728,1575525,2549253,4124778,6674031,10798809,17472840,28271649,45744489,74016138,119760627,193776765,313537392,507314157,820851549,0,0,34,68,102,170,272,442,714,1156,1870,3026,4896,7922,12818,20740,33558,54298,87856,142154,230010,372164,602174,974338,1576512,2550850,4127362,6678212,10805574,17483786,28289360,45773146,74062506,119835652,193898158,313733810,507631968,821365778,0,0,55,110,165,275,440,715,1155,1870,3025,4895,7920,12815,20735,33550,54285,87835,142120,229955,372075,602030,974105,1576135,2550240,4126375,6676615,10802990,17479605,28282595,45762200,74044795,119806995,193851790,313658785,507510575,821169360,0,0,89,178,267,445,712,1157,1869,3026,4895,7921,12816,20737,33553,54290,87843,142133,229976,372109,602085,974194,1576279,2550473,4126752,6677225,10803977,17481202,28285179,45766381,74051560,119817941,193869501,313687442,507556943,821244385,0,0,144,288,432,720,1152,1872,3024,4896,7920,12816,20736,33552,54288,87840,142128,229968,372096,602064,974160,1576224,2550384,4126608,6676992,10803600,17480592,28284192,45764784,74048976,119813760,193862736,313676496,507539232,821215728,0,0,233,466,699,1165,1864,3029,4893,7922,12815,20737,33552,54289,87841,142130,229971,372101,602072,974173,1576245,2550418,4126663,6677081,10803744,17480825,28284569,45765394,74049963,119815357,193865320,313680677,507545997,821226674,0,0,377,754,1131,1885,3016,4901,7917,12818,20735,33553,54288,87841,142129,229970,372099,602069,974168,1576237,2550405,4126642,6677047,10803689,17480736,28284425,45765161,74049586,119814747,193864333,313679080,507543413,821222493,0,0,610,1220,1830,3050,4880,7930,12810,20740,33550,54290,87840,142130,229970,372100,602070,974170,1576240,2550410,4126650,6677060,10803710,17480770,28284480,45765250,74049730,119814980,193864710,313679690,507544400,821224090,0,0,987,1974,2961,4935,7896,12831,20727,33558,54285,87843,142128,229971,372099,602070,974169,1576239,2550408,4126647,6677055,10803702,17480757,28284459,45765216,74049675,119814891,193864566,313679457,507544023,821223480,0,0,1597,3194,4791,7985,12776,20761,33537,54298,87835,142133,229968,372101,602069,974170,1576239,2550409,4126648,6677057,10803705,17480762,28284467,45765229,74049696,119814925,193864621,313679546,507544167,821223713,0,0,2584,5168,7752,12920,20672,33592,54264,87856,142120,229976,372096,602072,974168,1576240,2550408,4126648,6677056,10803704,17480760,28284464,45765224,74049688,119814912,193864600,313679512,507544112,821223624,0,0,4181,8362,12543,20905,33448,54353,87801,142154,229955,372109,602064,974173,1576237,2550410,4126647,6677057,10803704,17480761,28284465,45765226,74049691,119814917,193864608,313679525,507544133,821223658,0,0,6765,13530,20295,33825,54120,87945,142065,230010,372075,602085,974160,1576245,2550405,4126650,6677055,10803705,17480760,28284465,45765225,74049690,119814915,193864605,313679520,507544125,821223645,0,0,10946,21892,32838,54730,87568,142298,229866,372164,602030,974194,1576224,2550418,4126642,6677060,10803702,17480762,28284464,45765226,74049690,119814916,193864606,313679522,507544128,821223650,0,0,17711,35422,53133,88555,141688,230243,371931,602174,974105,1576279,2550384,4126663,6677047,10803710,17480757,28284467,45765224,74049691,119814915,193864606,313679521,507544127,821223648,0,0,28657,57314,85971,143285,229256,372541,601797,974338,1576135,2550473,4126608,6677081,10803689,17480770,28284459,45765229,74049688,119814917,193864605,313679522,507544127,821223649,0,0,46368,92736,139104,231840,370944,602784,973728,1576512,2550240,4126752,6676992,10803744,17480736,28284480,45765216,74049696,119814912,193864608,313679520,507544128,821223648,0,0,75025,150050,225075,375125,600200,975325,1575525,2550850,4126375,6677225,10803600,17480825,28284425,45765250,74049675,119814925,193864600,313679525,507544125,821223650,0,0,121393,242786,364179,606965,971144,1578109,2549253,4127362,6676615,10803977,17480592,28284569,45765161,74049730,119814891,193864621,313679512,507544133,821223645,0,0,196418,392836,589254,982090,1571344,2553434,4124778,6678212,10802990,17481202,28284192,45765394,74049586,119814980,193864566,313679546,507544112,821223658,0,0,317811,635622,953433,1589055,2542488,4131543,6674031,10805574,17479605,28285179,45764784,74049963,119814747,193864710,313679457,507544167,821223624,0,0,514229,1028458,1542687,2571145,4113832,6684977,10798809,17483786,28282595,45766381,74048976,119815357,193864333,313679690,507544023,821223713,0,0,832040,1664080,2496120,4160200,6656320,10816520,17472840,28289360,45762200,74051560,119813760,193865320,313679080,507544400,821223480,0,0,1346269,2692538,4038807,6731345,10770152,17501497,28271649,45773146,74044795,119817941,193862736,313680677,507543413,821224090,0,0,2178309,4356618,6534927,10891545,17426472,28318017,45744489,74062506,119806995,193869501,313676496,507545997,821222493,0,0,3524578,7049156,10573734,17622890,28196624,45819514,74016138,119835652,193851790,313687442,507539232,821226674,0,0,5702887,11405774,17108661,28514435,45623096,74137531,119760627,193898158,313658785,507556943,821215728,0,0,9227465,18454930,27682395,46137325,73819720,119957045,193776765,313733810,507510575,821244385,0,0,14930352,29860704,44791056,74651760,119442816,194094576,313537392,507631968,821169360,0,0,24157817,48315634,72473451,120789085,193262536,314051621,507314157,821365778,0,0,39088169,78176338,117264507,195440845,312705352,508146197,820851549,0,0,63245986,126491972,189737958,316229930,505967888,822197818,0,0,102334155,204668310,307002465,511670775,818673240,0,0,165580141,331160282,496740423,827900705,0,0,267914296,535828592,803742888,0,0,433494437,866988874,0,0,701408733};
int t;
int q[300];
int main()
{
    //freopen("fib.in","r",stdin);
    //freopen("fib.out","w",stdout);
    cin>>t;
    for(int i=1;i<=t;i++)
    {
        cin>>q[i];
    }
    for(int ii=1;ii<=t;ii++)
    for(int i=0;i<=1122;i++)
    {
        if(q[ii]==ans[i])
        {
        cout<<"Yes"<<endl;
        break;
    }
        if(i==1122)cout<<"No"<<endl;
    }
}

 

2.

#include<bits/stdc++.h>
using namespace std;
long long f[199999];
map<long long,bool>a;
int t;

int main()
{
    freopen("fib.in","r",stdin);
    freopen("fib.out","w",stdout);
    f[1]=1;
    f[2]=1;

    for(int i=3; i<=47; i++)
    {
        f[i]=f[i-1]+f[i-2];
    }

    for(int i=0; i<=47; i++)
        for(int j=0; j<=47; j++)
        {
            long long w=f[i]*f[j];
            if(w<1e9&&!a[w])
            {
                a[w]=1;
            }
        }

    scanf("%d",&t);
    while(t--)
    {
        int x;
        scanf("%lld",&x);
        if(a[x]) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

 

2、 一样远(equal.pas/cpp)
【问题描述】
企鹅国的城市结构是一棵树,有 N 座城市和 N-1 条无向道路,每条道路都一样长。豆豆
和豆沙准备去参加 NOIP(National Olympiad in Informatics for Penguin),但是他们住
在不同的地方,豆豆住在城市 A,豆沙住在城市 B。他们想找一个距离 A 和 B 一样远的集合
地点,所以他们想知道有多少个城市满足这个要求?
由于他们会参加很多次 NOIP,所以有很多个询问。
【输入格式】
第一行一个整数 N 代表城市个数。
接下来 N-1 行,每行两个数字 F 和 T,表示城市 F 和城市 T 之间有一条道路。
接下来一行一个整数 M 代表询问次数。
接下来 M 行,每行两个数字 A 和 B,表示这次询问的城市 A 和城市 B(A 可能与 B 相同)。
【输出格式】
输出 M 行,每行一个整数表示到 A 和 B 一样远的城市个数。
【输入样例 1】
4
1 2
2 3
2 4
2
1 2
1 3
【输出样例 1】
0 2
【输入样例 2】
4
1 2
2 3
2 4
2
1 1
3 3
【输出样例 2】
4 4
【数据范围】
对于 30%的数据: N,M≤1000;
对于另外 10%的数据: A=B;
对于另外 30%的数据: 保证树的形态随机;
对于 100%的数据: 1≤N,M≤100000。

30%:
每次询问从两个端点开始 BFS 算出每个点到两个端点的距离。
然后暴力即可。
复杂度 O(NM)。
另外 10%:
全部输出 N 即可。
另外 30%:
由于树高有限,所以暴力找到 A 和 B 的中点,然后答案就为“N-A 来的子树大小-B
来的子树大小”。
100%:
对于 A 的深度=B 的深度,中点为 A 和 B 的 LCA。
如果不等于,可以先用 LCA 求出 A、 B 的距离,再在树上倍增求出 AB 的中点。
注意特判 AB 终点不存在的情况。

1.

 

//
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
struct node
{
    int to;
    int next;
} edge[300000];
int head[100005],num,dep[100005],fa[100005][23],size[100005],s;
void add(int x,int y)
{
    edge[++num].to=y;
    edge[num].next=head[x];
    head[x]=num;
}
int n;
inline int read()  
{
    int s=0;
    char c=getchar();
    while (c<'0' || c>'9') c=getchar();
    while (c>='0' && c<='9') s=s*10+c-'0',c=getchar();
    return s;
}
void dfs(int i,int f)
{
    fa[i][0]=f;
    for(int j=1; j<=20; j++)fa[i][j]=fa[fa[i][j-1]][j-1];
    for(int j=head[i]; j; j=edge[j].next)
    {
        int v=edge[j].to;
        if(v!=f)
        {
            dep[v]=dep[i]+1;
            dfs(v,i);
            size[i]=size[i]+size[v];
        }
    }
}
int LCA(int x,int y)
{
    if(dep[x]<dep[y])
        swap(x,y);
    int k=dep[x]-dep[y];
    for(int i=0; i<=s; i++)
        if(k&(1<<i)) x=fa[x][i];
    if(x==y) return x;
    for(int i=s; i>=0; i--)
        if(fa[x][i]!=fa[y][i])
            x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
int len,m,ans;
int main()
{
    //freopen("equal.in","r",stdin);
    //freopen("equal.out","w",stdout);
    n=read();
    s=ceil(log2(n));
    int a,b;
    for(int i=1; i<n; i++)
    {
        a=read(),b=read();
        add(a,b);
        add(b,a);
        size[i]=1;
    }
    size[n]=1;
    dep[1]=0;
    dfs(1,0);
    m=read();
    for(int i=1; i<=m; i++)
    {
        cin>>a>>b;
        if(a==b)
        {
            cout<<n<<endl;
            continue;
        }
        int Key=LCA(a,b);
        len=dep[a]+dep[b]-2*dep[Key];
        if(len%2==1)//从0开始的深度
        {
            cout<<"0"<<endl;
            continue;
        }
        int d=len/2;
        if(dep[a]<dep[b]) swap(a,b);
        int ff,e;
        if(dep[a]==dep[b])
        {
             e=a;ff=b;
            for(int i=20;i>=0;i--)//用倍增来找点
                if((d-1)&(1<<i)) e=fa[e][i];
            for(int i=20;i>=0;i--)
                if((d-1)&(1<<i)) ff=fa[ff][i];
                ans=n-size[e]-size[ff];
        }
        else
        {
             e=a;
             ff=a;
            for(int i=0; i<=s; i++)
                if(d&(1<<i)) e=fa[e][i];
            for(int i=0; i<=s; i++)
                if((d-1)&(1<<i)) ff=fa[ff][i];
            ans=size[e]-size[ff];
        }
        //cout<<Key<<" ";
        cout<<ans<<endl;
    }
    return 0;
}

 2.

#include<bits/stdc++.h>
using namespace std;

inline int read(int &x){
    x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
}

const int N=1<<17;

vector<int>g[N];
int n,m,p[N][17],sz[N],d[N];

void dfs(int x){
    sz[x]=1;
    for(int i=0;i<g[x].size();i++){
        int v=g[x][i];
        if(v!=p[x][0]){
            p[v][0]=x,d[v]=d[x]+1;
            for(int j=1;j<17;j++)
                p[v][j]=p[p[v][j-1]][j-1];
            dfs(v),sz[x]+=sz[v];
        }
    }
}

int get(int x,int d){
    for(int i=0;i<17;i++)
        if(d & (1<<i))    x=p[x][i];
    return x;
}

int LCA(int x,int y){
    x=get(x,d[x]-d[y]);
    if(x==y) return x;
    for(int i=16;i>=0;i--)
        if(p[x][i]!=p[y][i]) x=p[x][i],y=p[y][i];
    return p[x][0];
}

int main(){
    freopen("equal.in","r",stdin);
    freopen("equal.out","w",stdout);
     
    int x,y;
    read(n);
    for(int i=1;i<n;i++)
        read(x),read(y),
        g[x].push_back(y),
        g[y].push_back(x);

    for(int i=0;i<=17;i++)
        p[1][i]=1;
    dfs(1);

    for(read(m);m--;){
        read(x),read(y);
        if(d[x]<d[y])
            swap(x,y);
        if(x==y)
            printf("%d\n",n);
        else{
            int z=LCA(x,y);
            int ds=d[x]-d[z]+d[y]-d[z];
            if(ds&1)
                puts("0");
            else{
                ds>>=1;
                int u=get(x,ds);
                if(u==z){
                    x=get(x,ds-1);
                    y=get(y,ds-1);
                    printf("%d\n",n-sz[x]-sz[y]);
                }else{
                    x=get(x,ds-1);
                    printf("%d\n",sz[u]-sz[x]);
                }
            }
        }
    }
    return 0;
}

 

3、 拆网线(tree.pas/cpp)
【问题描述】
企鹅国的网吧们之间由网线互相连接,形成一棵树的结构。现在由于冬天到了,供暖部
门缺少燃料,于是他们决定去拆一些网线来做燃料。但是现在有 K 只企鹅要上网和别人联机
游戏,所以他们需要把这 K 只企鹅安排到不同的机房(两只企鹅在同一个机房会吵架),然
后拆掉一些网线,但是需要保证每只企鹅至少还能通过留下来的网线和至少另一只企鹅联机
游戏。
所以他们想知道,最少需要保留多少根网线?
【输入格式】
第一行一个整数 T,表示数据组数;
每组数据第一行两个整数 N, K,表示总共的机房数目和企鹅数目。
第二行 N-1 个整数,第 i 个整数 Ai 表示机房 i+1 和机房 Ai有一根网线连接(1≤Ai≤i)。
【输出格式】
每组数据输出一个整数表示最少保留的网线数目。
【输入样例】
2
4 4
1 2 3
4 3
1 1 1
【输出样例】
2 2
【数据范围】
对于 30%的数据: N≤15;
对于 50%的数据: N≤300;
对于 70%的数据: N≤2000;
对于 100%的数据: 2≤K≤N≤100000, T≤10。
30%:暴力枚举删除哪些边,然后验证即可。

50%: DP[i][j][k]表示当前子树根节点为 i,与子树中 j 个点相连,是否已经安排了 k
只企鹅。
复杂度 O(N3)。
70%:
考虑 DP。
DP[i][j]表示 i 与子树中 j 个点相连,最多已经安排了多少企鹅。
复杂度 O(N2)。
100%:
一条边可以用两只企鹅站,这样的一条点对,越多越好。
如果是 ans 对点, ans*2≥k,那么只需要 (k+1)/2 条边。
否则,需要 ans + (k-ans*2) 条边。
现在问题就转为求这样的点对有多少。
dp[i][0]表示以 i 为根的子树中能够两两配对的最大点数,不包含节点 i。
dp[i][1]表示以 i 为根的子树中能够两两配对的最大点数,包含节点 i。
转移方程:
dp[u][0]=Σv 是 u 的儿子 dp[v][1];
dp[u][1]=max(dp[u][1],dp[u][0]-dp[v][1]+dp[v][0]+2)。
最后 max(dp[1][0],dp[1][1])就是 ans 了。

#include <bits/stdc++.h>
using namespace std;

inline int read(int &r)
{
    int f=1,c=getchar();
    r=0;
    while(c<'0'||c>'9')
    {
        if(c=='-') f=-1;
        c=getchar();
    };
    while(c>='0'&&c<='9')r=r*10+c-'0',c=getchar();
    return r*f;
}

const int maxn = 100005;
vector<int> g[maxn];
int d[maxn][2]; // 0 ??
bool vis[maxn];

void dp(int u,int fa)
{
    if(vis[u]) return;
    vis[u] = 1;

    d[u][0] = d[u][1] = 0;
    int sum = 0;
    for(int i=0; i < (int)g[u].size(); i++)
    {
        int v = g[u][i];
        if(v==fa) continue;
        dp(v,u);
        d[u][1] += max(d[v][0],d[v][1]);
        sum+=d[v][0];
    }

    for(int i=0; i < (int)g[u].size(); i++)
    {
        int v = g[u][i];
        if(v==fa) continue;
        d[u][0] = max(d[u][0],sum-d[v][0]+d[v][1]+1);
    }

}

int T;
int N,K;

int main()
{
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);

    read(T);
    while(T--)
    {
        read(N);
        read(K);

        for(int i=0; i <= N; i++)
            g[i].clear();
        memset(vis,0,sizeof(vis));

        int u;
        for(int i=1; i < N; i++)
        {
            read(u);
            g[u].push_back(i+1);
            g[i+1].push_back(u);
        }

        dp(1,-1);

        int ans = max(d[1][1],d[1][0]);
        if(ans*2>=K)
            printf("%d\n",(K+1)/2);
        else
            printf("%d\n",ans+K-(ans*2));
    }
    return 0;
}

法二;直接贪心,每次删除两个点

//
#include<stdio.h>
#include<bits/stdc++.h>
int f[110000],t,n,k,y,v[110000],a,i;
int r()
{
    int s=0;
    char c=getchar();
    while (c<'0' || c>'9') c=getchar();
    while (c>='0' && c<='9') s=s*10+c-'0',c=getchar();
    return s;
}
main()
{
    t=r();
    for(y=1; y<=t; y++)
    {
        memset(v,0,sizeof(v));
        n=r(),k=r();
        a=0;
        for(i=2; i<=n; i++)f[i]=r();
        for(i=n; i>1; i--)if(!v[i]&&!v[f[i]])a++,v[f[i]]=1;
        if(a*2<k)a+=k-a*2;
        else if(a*2>k)a-=(a*2-k)/2;
        std::cout<<a<<std::endl;
    }
}

 

posted @ 2019-09-26 18:30  CXYscxy  阅读(548)  评论(0编辑  收藏  举报
Live2D