2015西电暑期集训第一场(锘爷系列)

1079: 锘爷与数列

时间限制: 1 Sec   内存限制: 128 MB

题目描述

锘爷拿到了一个长度为n的数列,数列中每个数ai都满足1<=ai<=m。请你帮他找到一个连续子序列,使其中出现次数最多的数的出现次数 与 出现次数最少的数的的出现次数 的差最大。输出这个差。 
2<=n<=100000 
2<=m<=10

输入

多组数据,第一行为数据组数T(1<=t<=10)。每组数据第一行包含两个数n,m。第二行为这个数列,每两个数之间用空格隔开。

输出

输出格式 
每组数据输出一个数,即最大的差值。

样例输入

2
10 2
1 1 2 2 1 2 1 1 1 1
10 3
2 3 2 1 1 1 1 1 1 1

样例输出

4
6

提示

121111中 出现次数最多的为1,出现5次。最少的为2,出现1次,而不是3,4,5……因为他们没有出现。

来源


分析:哎!这道题可难到我了。

思路:两个for循环枚举最多的数和出现次数最少的数,然后遍历数组,遇到最多的数,结果+1,最少的数-1,其他数不变。当结果为负时,重新把结果置0.中间要加个判断变量,最少次数的数是否出现。如果没出现,就在结果上-1。我开始一直WA,后来发现必须枚举数组里存在的数,后来加了个used数组才AC。


CODE:

#include <iostream>
#include <string.h>
using namespace std;
 
int main()
{
    const int maxn=100005;
    int t; cin>>t;
    int n,m,arr[maxn];
    while(t--){
        int MAX=-maxn;
        cin>>n>>m;
        bool used[maxn];
        memset(used,false,sizeof(used));
        for(int i=1;i<=n;i++){
            cin>>arr[i];
            used[arr[i]]=true;
        }
        bool judge=true;
        for(int i=1;i<n;i++)
            if(arr[i]!=arr[i+1])
                judge=false;
        if(judge){
           cout<<0<<endl;
           continue;
        }
        for(int i=1;i<=m;i++){
            for(int j=1;j<=m;j++){
                if(i!=j&&used[i]&&used[j]){
                    int brr=0;
                    bool flag=false;
                    for(int k=1;k<=n;k++){
                        if(arr[k]==i)
                            brr++;
                        else if(arr[k]==j){
                            flag=true;
                            brr--;
                        }
                        if(brr<0){
                            flag=false;
                            brr=0;
                        }
                        else if(brr>MAX&&flag){
                            MAX=brr;
                        }
                        if(brr-1>=0&&brr-1>MAX&&!flag)
                            MAX=brr-1;
                    }
                }
            }
        }
        if(MAX>=0)
            cout<<MAX<<endl;
        else
            cout<<0<<endl;
    }
    return 0;
}

1080: 锘爷与跳楼塔

时间限制: 1 Sec   内存限制: 128 MB

题目描述

锘爷发现西电跳楼塔一种非常诡异的现象:它会对周围区域产生一种诡异的辐射。假设分别以正东方向、正北方向为x轴、y轴正方向建立平面直角坐标系,且跳楼塔在坐标原点,那么在点(x,y)受到的辐射强度面密度(单位面积的辐射强度)在数值上等于该点到原点的曼哈顿距离(即|x|+|y|)除以到原点的最短距离。

锘爷想让你帮他算一算在以跳楼塔为圆心,半径为r的圆内所受到的总辐射强度为多少。

输入

多组数据,处理到EOF

每组数据包含一个整数r,且≤ r ≤ 104

输出

每组数据输出一行,结果四舍五入到个位。

样例输入

1
3
5

样例输出

4
36
100

提示

来源


分析:水题,看样例就能猜到公式。

CODE:

#include <iostream>
using namespace std;
 
int main()
{
    int r;
    while(cin>>r)
        cout<<r*r*4<<endl;
    return 0;
}

1081: 锘爷与矩阵

时间限制: 1 Sec   内存限制: 128 MB

题目描述

锘爷有一二阶方阵A={Aij},且

A11=a, A12=b, A21=c, A22=d

我们都知道,矩阵A的行列式的值

det(A) = ad - bc

现在你知道a的取值范围为闭区间[a1,a2]内的实数,同样的,b为[b1,b2],c为[c1,c2],d为[d1,d2],你的任务是判断是否存在使得det(A)=0的矩阵A。

输入

多组数据,处理到EOF。

每组数据包含一行,每行为8个正整数,分别表示a1, a2, b1, b2, c1, c2, d1, d2,且8个数都在[1,108]范围内,而且a1<=a2, b1<=b2, c1<=c2, d1<=d2。

输出

对于每组数据,如果存在符合条件的矩阵,输出“YES”,否则输出“NO”。

样例输入

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

样例输出

YES
NO

提示

来源


分析:被坑了一下,如果int a=1e7,b=1e7,并且 long long c=a*b。但是,c的结果却不为1e14。

思路:由于四个数都可以取区间内的任意实数,ad 和 bc 也分别可以取[a1d1, a2d2] 和 [b1c1, b2c2] 内的任意实数。判断一下区间的交是否为空就行了。


CODE:

#include <iostream>
using namespace std;
 
int main()
{
    long long a1,a2,b1,b2,c1,c2,d1,d2;
    while(cin>>a1>>a2>>b1>>b2>>c1>>c2>>d1>>d2){
        long long xmin=a1*d1,xmax=a2*d2,ymin=b1*c1,ymax=b2*c2;
        if(xmin>ymax||xmax<ymin)
            cout<<"NO"<<endl;
        else
            cout<<"YES"<<endl;
    }
    return 0;
}

1082: 锘爷与羽毛球

时间限制: 1 Sec   内存限制: 128 MB

题目描述

锘爷作为实验室里为数不多的非单身汪,为了避免下次出校约(yue)会(囧)的时候变成一个死宅,锘爷决定带领实验室众码农去锻炼变成阳光宅男,鉴于实验室里的杰师傅海拔太高,打篮球其他众农会被虐爆,有违党的和谐之路,于是大家一致同意去打羽毛球……现在,对于每个码农i,都有一个想参与的最多打球的场次ai,现在问在所有的码农之间最多可以进行多少次1vs1的比赛场数?(我们认为两个人之间是可以重复solo的……)

输入

第一行,T,表示总的测试组数。之后对于每组测试数据,第一行是一个数字n(1<=n<=10^5,不要问我实验室哪来这么多码农),第二行是n个数字,依次表示每个码农想参与的最多赛场数(0<=ai<=10^9,不要问我为什么可以打这么多场羽毛球,作为一个码农,有些与众不同是可以理解的)。

输出

每组一行输出,输出最多可以进行的比赛场数

样例输入

2
3
2 3 3
3
6 6 6

样例输出

4
9

提示

我不会告诉你这是一道挺简单的送分题……

来源


官方题解:

分类:图论

难度:中易

这题就是给一个没有自环的无向图中每个点度的上限,求图中至多有多少边。如果去掉没有自环的条件,答案就是 ⌊∑v∈Vdegree(v)2⌋,然而有自环的时候就不一样了,例如数据 n = 1,a1 = 500 的答案是 0。容易看出,答案不能超过 ∑v∈Vdegree(v) − maxv∈V degree(v),否则度最大的节点就会形成自环。所以答案是这两个式子的最小值。

时间复杂度:O(|V |)


CODE:

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
 
int main()
{
    int t; cin>>t;
    while(t--){
        int n; cin>>n;
        long long x,maxx=-1000,sum=0;
        while(n--){
            cin>>x;
            if(x>maxx)
                maxx=x;
            sum+=x;
        }
        long long ans=min(sum/2,sum-maxx);
        cout<<ans<<endl;
    }
    return 0;
}

1083: 锘爷与括号

时间限制: 1 Sec   内存限制: 128 MB

题目描述

数据结构老师给了锘爷一个长度为n的字符串,该串仅由( 和 ) 组成,比如((()))(((, 
老师想让锘爷求所有括号都匹配的最长的子序列的长度。  输出最长子序列的长度即可。 
这个问题显然难不倒锘爷,不幸的是锘爷又与妹子一块出去玩了(不要问锘爷去干什么了), 所以想让你帮忙解决这个问题。

匹配的定义为:
(1)空串是匹配的。
(2)若A是匹配的,则(A)是匹配的。
(3)若A、B是匹配的,则AB是匹配的。
例如() ()() (())()都是匹配的。
子序列的定义为:某个序列的子序列是从最初序列通过去除某些元素但不破坏余下元素的相对位置(在前或在后)而形成的新序列。

输入

第一行整数T,代表数据组数(T不超过100) 
接下来T行,每行一个字符串S, 长度不超过201508

输出

如果不存在匹配的子序列输出0, 否则输出满足条件的最长子序列的长度,每组输出占一行。

样例输入

2
())(())(())(
)(

样例输出

10
0

提示

来源


官方题解:

分类:模拟

难度:中易

假设有一个栈,每次碰见左括号就放进去,碰见右括号就从栈里拿出一个左括号与之配对,如果栈空就丢弃该右括号。最后丢弃栈中的所有多余左括号。由栈的性质,除了丢弃的括号外,剩下的括号一定配好了对。因为栈里面全是左括号,所以不用真的开一个栈,只要用一个数记录栈的大小就行了。最后答案就是原来的长度减掉丢弃的括号个数。

时间复杂度:O(|S|)


CODE:

#include <iostream>
#include <string.h>
using namespace std;
 
int main()
{
    int t; cin>>t;
    while(t--){
        char c[1000005],tmp[1000005];
        int cntl=0,cntr=0;
        cin>>c;
        int len=strlen(c);
        for(int i=0;i<len;i++){
            if(c[i]=='(')
                cntl++;
            else if(cntl)
                cntl--;
            else
                cntr++;
 
        }
        cout<<len-cntl-cntr<<endl;
    }
    return 0;
}

1084: 锘爷与信号

时间限制: 1 Sec   内存限制: 128 MB

题目描述

“lnever,老师真的尽力了。”听到这句话的锘爷无法抑制内心的压抑,就跑出来报复社会了。把你们这群学霸抓进了小黑屋,让你们帮他算算锘爷补考能不能过。 
学霸们都知道,信号这种课,章节前后有的相关很大,所以锘爷必须按照一定顺序来复(yu)习,比如卷积必须在傅里叶变换的前面学习。现在锘爷已经请学霸帮他把信号划分成10个重点章节。每个章节有自己的分值Si。保证S1+..S10==100。你要相信锘爷的预习能力,他3天就能看完一个章节呢~~~并且看过的章节一定会考!考了他一定可以拿到满分!现在告诉你这些章节的前后顺序,并且知道懒惰的锘爷会放在信号上的复习时间K天 0<K<=30,为了简单起见K始终是3的倍数。你要来计算在合理复习的情况下,他能不能及格(分数值总和大于等于60),如果可以,请输出一行为得分的最大值,如果不可以~~~他把你抓来不是为了让你告诉他他过不了的,如果锘爷真的过不了,你就留下一句话:"I chose to die"

输入

多组数据,处理到文件结束。 
第1行一个M,表示有M个顺序关系(保证不会有环) 
接下来M行每行有两个数u,v,表示v必须在复习了u之后才可以复习。 
第M+2行十个数,表示S1到S10,章节的分值。 
最后M+3行一个K,表示小诺复习的天数,k保证为3的倍数。

输出

对于每组数据输出1行,包含一个整数,表示最大得分,或者"I chose to die"。

样例输入

2
1 3
2 4
10 10 10 10 10 10 10 10 10 10
6

样例输出

I chose to die

提示

来源


分析:这道题卡死我了,后来我才明白我的BUG所在,没有考虑完全。发现章节可以拥有很多前章节必须复习,某个章节复习了,其他章节才能复习。WA26次,我最多的一次,我此刻的心情是I chose to die。


CODE:

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

int arr[15],n,k;
int gra[15],ans;
int par[10005],son[10005];

void dfs(int pre,int cnt)
{
    if(cnt==k){
        int sum=0;
        for(int i=0;i<cnt;i++)
            sum+=gra[arr[i]];
        if(sum>ans)
            ans=sum;
        return ;
    }
    for(int i=pre;i<=10;i++){
        arr[cnt]=i;
        bool flag=true;
        for(int j=0;j<n;j++){
            if(arr[cnt]==son[j]){
                flag=false;
                for(int k=0;k<cnt;k++){
                    if(arr[k]==par[j]){
                        flag=true;
                        break;
                    }
                }
                if(!flag)
                    break;
            }
        }
        if(!flag)
            continue;
        dfs(i+1,cnt+1);
    }
    return ;
}

int main()
{
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++)
            scanf("%d%d",&par[i],&son[i]);
        for(int i=1;i<=10;i++)
            scanf("%d",&gra[i]);
        scanf("%d",&k);
        k/=3;
        ans=-1000;
        dfs(1,0);
        if(ans>=60)
            printf("%d\n",ans);
        else
            printf("I chose to die\n");
    }
    return 0;
}

1085: 锘爷与粉丝

时间限制: 3 Sec   内存限制: 128 MB

题目描述

大家都知道锘爷是西电最吊的ACMer,所以都来Orz他。锘爷的宿舍周围有2k个建筑物,排成一个环,按顺时针顺序编号为0~2k-1,每个建筑物里面都有一些ACMerOrz锘爷。 下图是k=2的情况。

因为锘爷太吊了,每个正在Orz锘爷的ACMer每分钟都会叫来更多的ACMer,一起Orz锘爷。对于每个ACMer,在一单位时间内,他会叫来biACMer,到顺时针方向距离他自己i的建筑物去Orz锘爷(0≤i<2k)。
我们已经知道一开始在编号为i0≤i<2k)的建筑物有aiACMerOrz锘爷,那么t单位时间后,每个建筑物中有多少ACMerOrz锘爷呢?

因为Orz锘爷的ACMer很多,而且人数随t指数增加,最后会多到高精度都存不下的地步,你只要求出答案对99993601的模就行了。

对于100%的数据有0≤k≤100≤ai, bi<999936010≤t≤109

输入

多组数据(最多20组),以EOF结束。

每组数据,第一行2个整数k, t,以空格分割。
第二行2k个整数ai,以空格分割。
第三行2k个整数bi,以空格分割。

输出

对于每组数据,先输出一行”Orz”(不含引号),之后输出一行,包含2k个整数,表示t分钟后第0, 1, …, (2k-1)个建筑中Orz锘爷的人数对99993601的模,用空格分割。

样例输入

0 2
1
1
2 2
1 0 0 0
0 0 0 1

样例输出

Orz
4
Orz
1 0 1 2

提示

样例解释:

对于第一组样例,1ACMer在第1分钟叫来了另一个ACMer,第2分钟两个ACMer各叫来1ACMer,最后共有4个。

对于第二组样例,位于0ACMer在第1分钟叫来另一个ACMer,位于位置3。第2分钟两人各叫来1ACMer,分别位于位置32(从3顺时针数3个是3-0-1-2)。所以最后位置01ACMer,位置21ACMer,位置32ACMer


注意:

不要把”Orz”打成”orz”或者”OTZ”

行末不要有多余的空格。

来源


分析:做不来,超出了我的能力范围。

官方题解:

分类:数学

难度:难

已知序列 A[i] 和 B[i],求循环卷积 A ∗ (B + δ(i)) ∗ (B + δ(i))... ∗ (B + δ(i)),一共卷积 t 次。直接计算时间复杂度是 O(4kt),肯定超时。注意到卷积具有结合律,可以用快速幂,就优化到了 O(4klogt)。由于数据组数较多,模运算常数较大,还是过不掉。注意到 99993601 是质数,根据费马小定理有x99993600 = x1024×97560 ≡ 1 (mod 99993601)因此可以使用模乘法群上的傅里叶变换 [Cor+09, p. 923] 加速卷积,优化到 O(2klogt + 4k) = O(4k)。这已经可以通过本题,如果使用快速傅里叶变换还能进一步优化到 O(2k(k + logt))。

时间复杂度:O(4k) 或 O(2k(k + logt))

References

[Cor+09] Thomas H. Cormen et al. Introduction to Algorithms. 3rd ed. MIT Press, 2009.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值