智算之道初赛第二场(纯C)

​声控灯
小明正在上楼梯,当小明逐渐接近某层楼的时候,这层楼的声控灯检测到小明的脚步声便会亮起来,当小明逐渐远去的时候,声控灯由于一段时间内没检测到声音又会灭下去。
由于小明是匀速上楼的,而且他的速度把控得刚刚好,脚步声的音量也十分恰当,使得灯的亮灭呈现出这样的状态:他当前所在的楼层的声控灯是亮起的,他即将抵达的下一层楼的声控灯是亮起的,他刚刚离开的那层楼的声控灯也是亮起的。
现在你站在楼的外面,通过窗户看到了灯的亮灭状态,请推断小明现在在几楼?
输入格式
每个测试点包含以下内容:
第一行给出一个整数T,表示接下来给出T组测试数据

每组测试数据包含两行
第一行包含两个数 n,m,表示这栋楼一共有 n层,当前有 m盏灯是亮起的,而其余灯都是熄灭的
第二行包含m个整数,这些整数按照从小到大的顺序给出亮起的灯的序号
保证输入数据是符合实际情况的
输出格式
输出T行,每行包含一个数字,按照输入的顺序依次给出每组测试数据的答案。如果答案不确定,请输出-1
数据规模与约定

对于 50% 的数据,1<=T<=10,3<=n<=100,m=3
对于 100%的测试点,1<=T<=1000,1<n<=10^9,1<=m<=3

样例输入
2
5 3
1 2 3
5 2
1 2
样例输出
2
1

代码

#include<stdio.h>
int main()
{
    int i,t,n,m,a[3];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        for(i=0;i<m;i++)
            scanf("%d",&a[i]);
        if(n==1)
        	printf("1\n");
        else if(n==2)
        	printf("-1\n");
        else
        {
            if(m==2)
            {
                if(a[0]==1)
                    printf("1\n");
                else
                    printf("%d\n",n);
            }
            else
                printf("%d\n",a[1]);
        }
    }
}

构造字符串

给定若干个小写英文字母,请你用这些英文字母组成 n 个字符串,字符串可以是空串。要求这 n 个字符串的最长公共前缀最长。求出这个最长的长度。
所有字母都要用完,且每个字母只能用在一个字符串里。
名词解释
前缀 是指一个字符串从第一个字符开始的连续若干个字符组成的字符串。前缀可以为空串。比如字符串 “aab” 的前缀有四个,分别是 “”, “a”, “aa”, “aab”
我们说一个字符串 s 是某些串的 公共前缀,当且仅当这个串是每个字符
串的前缀。
每一个公共前缀都是一个字符串,是字符串就有长度。当n个串都确定下来的时候,这n个串的所有公共前缀也就确定下来了,而且可以证明公共前缀的数目是有限的,在这有限个公共前缀中,有一个公共前缀的长度是最长的,这个前缀就是最长公共前缀。
举个例子,假设现在有三个串:
abbc
abbde
abbe
这个三个串的最长公共前缀是 “abb”,长度为 3
再举个例子,假设现在有四个串:
abbd
bbd
abbd
abb
那么这四个串的最长公共前缀是"",长度为 0
输入格式
输入共有两行

第一行是一个整数 nn ,表示字符串的数量第二行包含 26 个非负整数。从前往后依次表示你拥有字母 a 的数目,字母 b 的数目,…,字母 z 的数目。

输出格式
输出一个非负整数,表示答案

数据规模与约定
对于 30% 的数据,除了字母 a 之外其它字母的数目都为 0
对于 100% 的数据,2≤n≤10^9 ,每种字母的个数也不超过 10^9

样例输入
2
3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
样例输出
2
样例解释
在第一个样例中,你拥有 3 个字母 a 和 3 个字母 b,可以构造这样的
两个串:“aba”,“abb”,这样最长公共前缀的长度是 2。可以证明不存在
更优秀的方案

样例输入 2
2
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
样例输出 2
0
样例解释 2
在第二个样例中,你拥有 1 个字母 a 和 1 个字母b,无论如何构造两个
串,都无法产生非空的公共前缀,因此答案是 0

代码

#include<stdio.h>
int main()
{
    int i,t,n,a;
    long long ans=0;
    scanf("%d",&n);
    for(i=0;i<26;i++)
    {
        scanf("%d",&a);
        ans+=a/n;
    }
    printf("%lld\n",ans);
}

情报战

现在我方已经查明,敌人通信所使用的加密方式依赖于一个长度为 n 的数列,只要得知了这个数列中每个数的值,我方便可破解敌方的通信。通过深入敌人内部的内线人员的艰苦奋斗,我方逐渐获得了一些有用的情报,通过这些情报,整个数列正在被不断地破解。
先后有 m 条情报被得知,每条情报是以下两种情况之一:

情况 1 :知道了数列中第 x个数的值
情况 2:知道了数列中第 x个数和第 y个数的和

每得知一条情报,我方都试图破解数列中元素的值作为情报部门核心技术人员的你,请编程实现如下功能:每次得知一条新情报,你都要计算当前已经能够确定出数列中的多少个数了你比较笨,对于情况 2 这种情报,只能在已知其中一个数的情况下推出另一个数,不能通过若干情况 2 的情报列方程求解
输入格式
第一行,两个正整数 n,m
接下来 m行,每行的第一个数是 type
如果 type=1,则接下来跟着一个整数 x,表示得知了数列中第 x 个数的值;
如果 type=2,则接下来跟着两个空格隔开的整数 x,y表示得知了第 x 个数和第 y 个数的和
输出格式
输出 m 行,每行包含一个非负整数,第 ii 行的非负整数表示在得知了前 ii 条情报之后数列中已经能够确定的数的数量
数据规模与约定
对于 20% 的数据,1≤n,m≤10,且只有第一种情报
对于 50% 的数据,1≤n,m≤5000
对于 100% 的数据,1≤n,m≤3×10^5
可能会有重复的情报,也可能出现 x=y的情况
样例输入
5 4
1 1
1 2
2 2 3
2 1 3
样例输出
1
2
3
3

代码

#include<stdio.h>
int par[1000005];
int qua[1000005];
int vis[1000005];
int findroot(int x)
{
    if(par[x]==x)
        return x;
    else
        return par[x]=findroot(par[x]);
}
void mix(int x,int y)
{
    if(findroot(x)==findroot(y))
        return ;
    if(vis[findroot(x)]||vis[findroot(y)])
        vis[findroot(x)]=vis[findroot(y)]=1;
    qua[findroot(y)]+=qua[findroot(x)];
    par[findroot(x)]=findroot(y);
}
int same(int x,int y)
{
    return findroot(x)==findroot(y);
}
int main()
{
    int i,n,m,op,cnt=0,a,b,x;
    scanf("%d %d",&n,&m);
    for(i=1;i<=n;i++)
    {
        qua[i]=1;
        par[i]=i;
        vis[i]=0;
    }
    for(i=1;i<=m;i++)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d",&x);
            if(!vis[findroot(x)])
            {
                cnt+=qua[findroot(x)];
                vis[findroot(x)]=1;
            }
        }
        else
        {
            scanf("%d %d",&a,&b);
            if(a==b)
            {
                x=a;
                if(!vis[findroot(x)])
                {
                    cnt+=qua[findroot(x)];
                    vis[findroot(x)]=1;
                }
            }
            else
            {
                if(vis[findroot(a)]!=vis[findroot(b)])
                    cnt+=(vis[findroot(a)]==0?qua[find
root(a)]:qua[findroot(b)]);
                mix(a,b);
            }
        }
        printf("%d\n",cnt);
    }
    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值