SDUT 2017 离散数学考试题

集合的包含

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

已知含n个元素的集合的子集A和B,用位串表示法判断是否有A⊆B。

Input

多组测试数据,每组测试数据第1行输入正整数n(1 <= n <= 100),表示集合元素个数,第2行输入位串表示法形式的集合A,第3行输入位串表示法形式的集合B。

Output

对于每组测试数据,若A⊆B则输出yes,反之则输出no。

Sample Input

10
1 0 1 0 1 0 1 0 1 0
1 0 1 0 1 0 1 0 1 0
10
0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1

Sample Output

yes
no
#include<iostream>

using namespace std;

int f1[100];
int f2[100];

int main()
{
    int n;
    while(cin>>n)
    {
        for(int i = 0; i < n; i++)
            cin>>f1[i];
        for(int i = 0; i < n; i++)
            cin>>f2[i];

        int fl = 1;
        for(int i = 0; i < n; i++)
            if(f1[i] && !f2[i])
            {
                fl = 0;
                break;
            }
            //如果f1中元素存在,而f2中不存在,退出循环

        if(fl) cout<<"yes\n";
        else cout<<"no\n";
    }
}




偏序关系

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

给定有限集上二元关系的关系矩阵,确定这个关系是否是偏序关系。

Input

多组测试数据,对于每组测试数据,第1行输入正整数n(1 <= n <= 100),第2行至第n+1行输入n行n列的关系矩阵。

Output

对于每组测试数据,若为偏序关系,则输出yes,反之,则输出no。

Sample Input

4
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
4
1 0 0 1
0 1 0 0
0 0 1 0
1 0 0 1

Sample Output

yes
no

Hint

偏序关系形式定义:设R是集合A上的一个二元关系,若R满足自反性、反对称性、传递性,则称R为A上的偏序关系

#include<stdio.h>

int f[200][200];

int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                scanf("%d", &f[i][j]);

        int fl = 1;

        for(int i = 1; i <= n; i++)//自反
            if(!f[i][i]) fl = 0;
            //既矩阵对角线上元素全为1满足自反性

        for(int i = 1; i <= n; i++)//反对称
            for(int j = 1; j < i; j++)
                if(f[i][j] && f[j][i]) fl = 0;
                //对角线两侧元素不对称则满足反对称

        for(int i = 1; i <= n; i++)//传递
            for(int j = 1; j <= n; j++)
                if(f[i][j])
                    for(int k = 1; k <= n; k++)
                        if(f[j][k] && !f[i][k]) fl = 0;
                        //选中元素的坐标,分别作为两行数,
                        //列数行若存在,则行数行也存在
                        //即满足传递关系

        if(fl) printf("yes\n");
        else printf("no\n");
    }
}




1.1联结词真值运算

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

已知命题变元p和q的真值,求它们的合取式(p∧q)、析取式(p∨q)、蕴涵式(p→q)、等值式(A<=>B)、与非式(p↑q)、或非式(p↓q)的真值。

Input

多组输入,每组测试数据输入两个0或1的整数p和q,1表示真值为真,0表示真值为假

Output

每组测试数据单独占一行,以空格隔开的6个0或1的整数,分别为p和q的合取式(p∧q)、析取式(p∨q)、蕴涵式(p→q)、等值式(A<=>B)、与非式(p↑q)、或非式(p↓q)的真值。

Sample Input

0 0

Sample Output

0 0 1 1 1 1

#include<stdio.h>

int main()
{
    int a, b;
    while(~scanf("%d%d", &a, &b))
    {
        printf("%d %d %d %d %d %d\n",
          a&&b, a||b,   !a||(a&&b), a==b, !(a&&b), !(a||b));
        //合取, 析取,      蕴涵,    等值,  与非,   或非
    }
}


哪款赛车最佳?

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

四名专家对四款赛车进行评论。
专家A说:a号赛车是最好的。
专家B说:b号赛车是最好的。
专家C说:c号不是最佳赛车。
专家D说:专家B说错了。
事实上只有一款赛车最佳,且只有一名专家说对了,其他三人都说错了。请编程输出最佳车的编号,以及哪位专家所对了。
 

Input

多组测试数据,对于每组测试数据,第 1 行输入3个正整数,表示a、b 、c的编号,编号x范围(1 <= x <= 4),且编号互不相同。
 

Output

对于每组测试数据,输出正整数x和字符ch,表示最佳车的编号以及说对的专家的编号,详细格式请参考样例。
 

Sample Input

2 4 3

Sample Output

3 D

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int S1,S2,S3,S4,best,a,b,c;
    while(~scanf("%d %d %d", &a, &b, &c))
    {
        for(best = 1; best <= 4; best++)
        //每个编号都试一试
        {
            S1= (best==a);
            S2= (best==b);
            S3= (best!=c);
            S4= !S2;
            //按照语义赋值
            if(S1+S2+S3+S4==1)
            {
                if(S1)
                    printf("%d %c\n",a,'A');
                else if(S2)
                    printf("%d %c\n",b,'B');
                else if (S3)
                    printf("c  is'n best\n");
                else if(S4)
                    printf("%d %c\n",c,'D');
                break;
            }
        }
    }
}





传递闭包

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

已知有n头牛,m次战斗关系,询问最终可以确定排名的牛的数量。

Input

多组测试数据,对于每组测试数据,第1行输入两个整数n(1 <= n <= 100)和m(0 <= m <= 4950),分别表示有n头牛和m次战斗关系,之后m行每行输入两个正整数x和y表示编号为x的牛可以战胜编号为y的牛,数据保证合法,询问可以确定排名的牛的数量。

Output

对于每组测试数据,输出整数ans,表示可以确定排名的牛的数量。

Sample Input

5 5
4 3
4 2
3 2
1 2
2 5

Sample Output

2

#include<stdio.h>
#include<string.h>

int f[101][101];

int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        int x, y;
        memset(f, 0, sizeof(f));
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d", &x, &y);
            f[x][y] = 1;
        }

        for(int i = 1; i <= n; i++)//warshall算法
            for(int j = 1; j <= n; j++)
                if(f[j][i])//被选中元素存在
                    for(int k = 1; k <= n; k++)
                        f[j][k] = f[j][k]||f[i][k];
                        //列行数必须满足一定关系

//        for(int i = 1; i <= m; i++)
//        {
//            for(int j = 1; j <= n; j++)
//                printf("%d ", f[i][j]);
//            printf("\n");
//        }

        int ans = 0;
        for(int i = 1; i <= n; i++)
        {
            int c = 1;
            for(int j = 1; j <= n; j++)
                if(i != j && (f[i][j] || f[j][i])) c++;
            if(c == n) ans++;
        }
        printf("%d\n", ans);
    }
}





建图

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

编程使得程序可以接受一个图的点边作为输入,然后显示出这个图。

Input

多组测试数据,对于每组测试数据,第一行输入正整数n(1 <= n <= 1000)和m,之后m行输入正整数x、y,表示在点x和点y之间存在有向边相连。

Output

对于每组测试数据,输出图的关系矩阵。

Sample Input

4 5
1 1
2 2
2 4
3 3
4 4

Sample Output

1 0 0 0
0 1 0 1
0 0 1 0
0 0 0 1

#include<iostream>
#include<string.h>
using namespace std;

int f[10000][10000];

int main()
{
    int n, m;
    while(cin>>n>>m)
    {
        memset(f, 0, sizeof(f));

        while(m--)
        {
            int x, y;
            cin>>x>>y;
            f[x][y] = 1;
        }

        for(int i = 1; i <= n; i++)
        {
            int fl = 1;
            for(int j = 1; j <= n; j++)
            {
                if(fl) fl = 0;
                else cout<<" ";
                cout<<f[i][j];
            }
            cout<<endl;
        }
    }
}







指定长度路径数

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

题目给出一个有n个节点的有向图,求该有向图中长度为k的路径条数。方便起见,节点编号为1,2,…,n,用邻接矩阵表示该有向图。该有向图的节点数不少于2并且不超过500.

 

 

例如包含两个节点的有向图,图中有两条边1 → 2 ,2 → 1 。

长度为1的路径有两条:1 → 2 和 2 →1 ;

长度为2的路径有两条:1 → 2 → 1和2 → 1 → 2 ;

偷偷告诉你也无妨,其实这个图无论k取值多少 ( k > 0 ),长度为k的路径都是2条。

Input

多组输入,每组输入第一行是有向图中节点的数量即邻接矩阵的行列数n。接下来n行n列为该图的邻接矩阵。接下来一行是一个整数k.k小于30.

Output

输出一个整数,即为图中长度为k的路径的条数。

Sample Input

3
0 1 0
0 0 1
0 0 0
2

Sample Output

1

#include<iostream>

using namespace std;

int a[504][504];//原始矩阵
int b[504][504];//ans
int c[504][504];//辅助数组
int n;


void show()
{
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
            cout<<b[i][j]<<" ";
        cout<<endl;
    }
}

int main()
{
    while(cin>>n)
    {
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
            {
                cin>>a[i][j];
                b[i][j] = a[i][j];
            }

        int k;
        cin>>k;
        while(--k)//矩阵相乘
        {
            for(int i = 0; i < n; i++)
                for(int j = 0; j < n; j++)
                {
                    c[i][j] = 0;
                    for(int k = 0; k < n; k++)
                        c[i][j] += b[i][k]*a[k][j];
                }

                for(int i = 0; i < n; i++)
                    for(int j = 0; j < n; j++)
                        b[i][j] = c[i][j];
        }

//        show();
        int ans = 0;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                ans += b[i][j];
        cout<<ans<<endl;
    }
}









离散题目11

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

给定一个数学函数写一个程序来确定该函数是否是双射的

Input

多组输入。 第一行输入三个整数n,m,k,分别表示集合a中的元素个数,集合b中的元素个数,集合a到b的映射个数。 第二行输入n个数,代表集合a中的元素。 第三行输入m个数,代表集合b中的元素。接下来k行,每行两个数,代表集合a中的元素x和x在集合b中的像y。

Output

每组数据输出一行,若F为a到b的双射,输出"YES", 否则输出"NO"。

Sample Input

5 5 5
1 2 3 7 8
2 5 6 9 0
1 9
3 2
2 6
7 0
8 5

Sample Output

YES
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int f[10001];
int f1[2][10001];//[1]用于计数
int f2[10001];
int f3[10001];
int main()
{
    int n, m, x, y, t, k;
    while(~scanf("%d%d%d", &n, &m, &k))
    {
        memset(f, 0, sizeof(f));
        memset(f1, 0, sizeof(f1));
        memset(f2, 0, sizeof(f2));
        memset(f3, 0, sizeof(f3));

        for(int i = 0; i < n; i++)
        {
            scanf("%d", &t);
            f1[0][t] = 1;
        }

        for(int i = 0; i < m; i++)
        {
            scanf("%d", &t);
            f2[t] = 1;
        }

        int fl = 1;

        for(int i = 0; i < k; i++)
        {
            scanf("%d%d", &x, &y);
            f3[i] = y;
            if(f1[0][x] && f2[y])
            {
                if(f1[1][x] && f[x] != y) fl = 0;//x多次出现且不满足单射
                else //x第一次出现
                {
                     f1[1][x]++;//x出现的次数
                     f[x] = y;//对应关系
                }
            }
            else fl = 0; //x或y不在集合里
        }

        int c = 0;//是否满射
        for(int i = 0; i < k; i++)
            if(f2[f3[i]])
            {
                f2[f3[i]] = 0;
                c++;
            }
        if(c != m) fl = 0;

        if(fl) printf("YES\n");
        else printf("NO\n");
    }
}





离散题目12

Time Limit: 1000 ms  Memory Limit: 65536 KiB

Problem Description

给出两个集合,以及两个集合上的关系。判断该关系能不能构成函数 

Input

多组输入。第一行数字表示集合A;第二行数字表示集合B;第三行一个数字N,表示关系的个数。以下N行,每行两个数字a b,用来描述关系a→b。0 < n < = 20000,集合A、B的大小不超过10000.

Output

每组数据输出一行,所给关系属于函数,输出’yes’ ,否则输出‘no’。 

Sample Input

1 2 3
4 5 6
3
1 4
2 5
3 6
1 2 3
4 5 6
3
1 4
1 5
1 6

Sample Output

yes
no

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;

char a[400000];//不开大点就等着RE吧
char b[400000];
int x[20000];
int y[20000];

int cmp(const void *a, const void *b)
{
    return *(int*)a > *(int *)b ? 1:-1;
}

int main()
{
    while(gets(a))
    {
        gets(b);
        //其实以上并没有什么卵用
        int fl = 1;
        int n;
        cin>>n;
        for(int i = 0; i < n; i++)
            cin>>x[i]>>y[i];
        qsort(x, n, sizeof(x[0]), cmp);

        for(int i = 1; i < n; i++)//用桶排还RE,只能用老方法
        {
            if(x[i]- x[i-1] == 0)//x是否相等
            {
                fl = 0;
                break;
            }
        }

        if(fl) cout<<"yes\n";
        else cout<<"no\n";
        getchar();//我也不知道为什么也要这样,如果用endl刷新了缓存区,还是RE
        //没有这玩意就等着RE吧
    }
}

祝大家考试顺利

猜你喜欢

转载自blog.csdn.net/qq458291868/article/details/80524806