SDUACM2017级个人排位赛2个人总结

2距离考完试比较近而且题比较难,所以就先写2了。

在这之前还是要先总结一下自己的所作所为,寒假不做题,上学期又一直浪,基础本来就不好,导致成绩急速下滑。这次划线我在省赛之下,所以,自己心里有点C数。

再说考试心态,紧张个P,动不动就浮躁,看个题看不完就看别的,老老实实正着看题!

比赛地址

A - Watching TV

  Gym - 101498A

题目链接——A

题目大意:熊孩子不学习,他爸怒了,让他以后只能看一个台(频率),你要帮助熊孩子选择节目尽可能多的台(频率)

题目不难,读完题就能写代码,题目的坑点在于

It is possible that two different channels have the same name and frequency.

这句话,这句话的意思是,如果一个频率有两个相同名称的节目,那么也算作两个节目。

也就是说去重是多余的。加了去重可能就Wr了.

AC 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef unsigned long long ll;
const int SIZE = 100010;
//map <int, map<string,bool> > vis;
map <int,int> countt;
string s;
int tmp,maxx,ans;

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        countt.clear();
        maxx = 0;
        int n;
        scanf("%d",&n);
        for(int i = 1;i <= n;i ++)
        {
   //         s.clear();
            cin>>s;
            scanf("%d",&tmp);
  //          if(!vis[tmp][s])
       //     {
              countt[tmp] ++;
        //      vis[tmp][s] = 1;
        //    }
            if(countt[tmp] > maxx)
            {
                maxx = countt[tmp];
                ans = tmp;
            }
            if(countt[tmp] == maxx)  ans = min(ans,tmp);
        }
        printf("%d\n",ans);
    }
    return 0;
}
/*
3
4
mbcone 12015
mbctwo 12015
mbcone 12015
mbcthree 12014
2
channelone 11112
channelyou 21112
1
watchme 12345
*/


B - Longest Prefix

  Gym - 101498B

B题链接

题目大意:给你两个字符串A,B,你可以对B进行一系列操作或者不操作,让A,B的公共前缀长度最长,求这个最长长度。

水题之2,A不动,B可以任意操作,所以只需要把B中各个字母的个数记下来,扫一遍A,发现一个字母c在B中有的就count[c]--;直到发现对于A中的某个字母count[c] == 0就break,记录下这个最长长度。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef unsigned long long ll;
const int SIZE = 100010;
int countb[233];
char s1[SIZE],s2[SIZE];
int main()
{
    int t;
    cin>>t;
    for(int j = 1;j <= t;j ++)
    {
        memset(countb,0,sizeof(countb));
        memset(s1,0,sizeof(s1));
        memset(s2,0,sizeof(s2));
        cin>>s1>>s2;
        int l1 = strlen(s1);
        int l2 = strlen(s2);
        for(int i = 0;i < l2;i ++)  countb[s2[i]-'a'+1] ++;
        int sum = 0;
        for(int i = 0;i < l1;i ++)
        {
            if(countb[s1[i]-'a'+1])
            {
                sum ++;
                countb[s1[i]-'a'+1] --;
            }
            else if(!countb[s1[i]-'a'+1])    break;
        }
        cout<<sum<<endl;
    }
    return 0;
}
/*
aaaabbbccd
abbcccdddd

3
hello hey
here there
you me
*/

C - Super Subarray

  Gym - 101498G

C题链接

题目大意:给定一个序列,求超级子序列的个数

超级子序列:序列中所有元素的和 % 每个元素都为0;

思路:考场上各种脑子瓦特。 这个数膜每个元素都是0,那么这个数肯定是这些元素公共最小公倍数(lcm)的倍数。而和的问题也很好解决,用前缀和可以做到O1查询。所以这个题我们需要做的就是枚举所有的子区间,复杂度是n^2.再看看数据范围,n上限2000,T是100 这样算下来复杂度是400000000,肯定是要TLE的。这时候考虑一下玄学优化,这里考虑 如果公共lcm大于n*1e9,那么无论哪些数的和加起来都不会是它的倍数,因为所有数加起来最大也就是n*1e9.这样我们就加一个类似于剪枝的操作就能过了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef unsigned long long ll;
const int SIZE = 2010;
int t,n;
ll sum,lcsum,num[SIZE],countt,maxx;
ll gcd(ll a,ll b){return b == 0 ? a : gcd(b,a%b);}
ll lcm(ll a,ll b){return a*b/gcd(a,b);}

int main()
{
	scanf("%d",&t);
	while(t--)
	{
		countt = 0;
		scanf("%d",&n);
		maxx = (ll)(n) * (ll)(1e9);
		for(int i = 1;i <= n;i ++)	scanf("%lld",&num[i]);
		for(int i = 1;i <= n;i ++)
		{
			sum = 0;
			lcsum = num[i];
			for(int j = i;j <= n;j ++)
			{
				sum += num[j];
				lcsum = lcm(lcsum,num[j]);
				if(sum % lcsum == 0)	countt ++;
				if(lcsum > maxx)	break;
			}
		}
		printf("%lld\n",countt);
	}
	return 0;
}

D - Two Subarrays

  Gym - 101498K 

E - Restaurant

  UVALive - 4851 

D 看懂了不太会做。。     E没看懂题。。

F - ENimEN

  UVA - 11892

F题链接

题目大意:原来的NIM游戏太无聊,这俩人玩出了花样,当前人拿完石子之后,如果当前堆仍有石子,那么下一个人必须从这堆里拿。

一直不太懂NIM游戏之类的博弈论问题。。这个也不例外。。 看了题解之后明白了,到自己做却就是不会推。。所以要补一下了。。。。

对于所有情况,当且仅当堆的个数为偶数且所有堆石子都为1个时piloop(后手)才能赢。

如果都是1的情况,那么奇数先手赢,偶数后手赢.

在不都是1的情况下,如果1的个数为奇数,其他堆都拿到只剩1个,那么后手只能拿完这堆,然后最终剩下奇数个1;

如果1的个数是偶数个,那么同样按照上述方法,不过当当前堆是最后一个不为1的堆时直接拿完。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int SIZE = 100010;
int t;

int main()
{
	scanf("%d",&t);
	while(t--)
	{
		int tmp,n,count = 0;
		scanf("%d",&n);
		for(int i = 1;i <= n;i ++)
		{
			scanf("%d",&tmp);
			if(tmp != 1)	count = -1;
			else if(count != -1)	count ++;
		}
		if(count != -1 && count % 2 == 0)	puts("piloop");
		else	puts("poopi");
	}
	return 0;
}

G - Neon Sign

  UVALive - 5846

G题目链接

题目大意:给定N边型(N >= 3),任意两点之间有连线,这些连线有两种颜色,输入每条线的颜色,问最终同色三角形的个数。

考试的时候没读懂题,其实是被那个图吓到了。

考完试再回顾这个题,一开始当然是想邻接矩阵存颜色,对每个点搜同色的边的组合,然后看第三条边颜色是否相同,复杂度N^3*T 肯定TLE。

其实这个题用了一个容斥原理思想。你想求同色三角形个数,不好求,能不能求总三角形减去非同色三角形。这个时候就应该想非同色三角形好不好求了。对于一个点,如果它直连两条边颜色不同,那么它肯定是非同色三角形。这样每个点直接red[i]*blue[i]就是非同色三角形个数了。 同时 对于每个非同色三角形,有两个顶点在计算时会把这个三角形计算进去,另一个点看来它直连两边是同色的(只有两色,要么是aab要么是abb)。所以这个sum要除以2。而总三角形个数是C(n,3),即代码里写的公式。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int SIZE = 100010;
int red[2333],blue[2333],n,t,tmp;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		memset(red,0,sizeof(red));
		memset(blue,0,sizeof(blue));
		scanf("%d",&n);
		for(int i = 1;i < n;i ++)
		{
			for(ll j = i+1;j <= n;j ++)
			{
				scanf("%d",&tmp);
				if(tmp == 0)
				{
					red[i] ++;
					red[j] ++; 
				}
				else	
				{
					blue[i] ++;
					blue[j] ++; 
				}
			}
		}
		int sum = 0;
		for(int i = 1;i <= n;i ++)	sum += red[i]*blue[i];
		int ans = n*(n-1)*(n-2)/6-sum/2;
		printf("%d\n",ans);
	}
	return 0;
}

H - A Bit Fun

  HDU - 4737 

H题链接

题目大意:给定一个序列,以及m,求序列中满足(i|a i+1|a i+2| ... | a j )< m   的子序列的个数。

这个题N<=100000,显而易见N^2算法过不了,但实际上N^2居然过了。。数据比较水。。随意了

N^2算法:对于每组数据,同样枚举所有子序列,但是这个枚举有边界,即当当前的 或和 大于或等于m时再往后找就没有意义了,因为或运算得到的结果一定大于当前数。所以按照这个方法枚举所有子序列计算结果即可。

同时想卡这个算法也很容易,只需要一组数据:

1
100000 2
1 1 1 1 1 1 1 …… 1 

所以数据水 不要在意了~

I - GCD Guessing Game

  UVALive - 5916

这题有歧义,不管了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值