daimayuan week3

T1:饿饿饭饭2

题目链接:饿饿 饭饭2 - 题目 - Daimayuan Online Judge

思路:

一个数A乘多次2或者3等于另外一个数B,那么数B除以多次2或者3也等于A。所以:如果这n个数乘多次2或3之后相同,那么这n个数对应除若干次2或3也会相等。

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

int n,a[200005],t;

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>t;
		for(int j=1;j<=t;j++){
			cin>>a[j];
			while(a[j]%2==0)a[j]/=2;//除若干次2
			while(a[j]%3==0)a[j]/=3;//除若干次3
		}
		int flag=1;
		for(int j=2;j<=t;j++){
			if(a[j-1]!=a[j]){
				flag=0;
				break;
			}
		}
		if(flag)cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
	return 0;
}

T2:子串分值和

题目链接:子串分值和 - 题目 - Daimayuan Online Judge

思路:

要查找每一个子串中出现的字母是很难的(时间复杂度很高),反向思维查找子串中某一个字母没有出现的子串数,然后用总的子串数减去该字母没有出现的子串数,就等于这个字母在子串中出现的数量。统计26个字母即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
string s;
ll ans,head,tail,k,n,f;
int main()
{
	cin>>s;
	n=s.size();
	//总体思路:
	for(char i='a';i<='z';i++){
		k=n*(n+1)/2;//长度为n的字符串有k个子串
		head=-1,tail=-1,f=0;
		//查找字母i未出现的子串个数
		for(int j=0;j<n;j++){
			if(s[j]==i){
				head=tail;tail=j;
				if(head==-1)k-=tail*(tail+1)/2;
				else k-=(tail-head)*(tail-head-1)/2;
				f=1;
			}
		}
		if(f){
			k-=(n-tail)*(n-tail-1)/2;//还要减去字母最后一次出现的位置到字符串的末尾
			ans+=k;//加上这个字母出现的次数
		}
	}
	cout<<ans<<endl;
 	return 0;
}

T3:蒟蒻

题目链接:http://oj.daimayuan.top/course/11/problem/605

思路:

用两个set容器分别以第一关键词为口感,价格排序,然后模拟。

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

int n;

set<pair<int,int> >pr;//价格为第一关键字
set<pair<int,int> >T;//口感为第一关键字

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		int x,w,t;
		scanf("%d",&x);
		if(x==1){
			scanf("%d%d",&w,&t);
			pair<int,int> p[3];
			int f1=0,f2=0;
			p[0]=make_pair(w,-1);//查找时候第二关键字必须为-1
			if(pr.lower_bound(p[0])!=pr.end()){//检查价格是否出现
				auto j=pr.lower_bound(p[0]);
				if((*j).first==w)f1=1;
			}
			p[0]=make_pair(t,-1);//查找时候第二关键字必须为-1
			if(T.lower_bound(p[0])!=T.end()){//检查口感是否出现
				auto j=T.lower_bound(p[0]);
				if((*j).first==t)f2=1;
			}
			if(f1||f2)continue;
			else pr.insert(make_pair(w,t)),T.insert(make_pair(t,w));//口感价格均未出现,放入篮子
		}
		else if(x==2){//去除价格最低的
			auto j=pr.begin();
			pair<int,int> p;
			p=make_pair((*j).second,(*j).first);
			pr.erase(j);T.erase(p);
		}
		else if(x==3){//去除口感最差的
			auto j=T.begin();
			pair<int,int> p;
			p=make_pair((*j).second,(*j).first);
			T.erase(j);pr.erase(p);
		}
	}
	long long ans=0;
	for(auto i:pr){
		ans+=(i.first);
	}
	cout<<ans<<endl;

 	return 0;
}

T4:锦标赛

题目链接:锦标赛 - 题目 - Daimayuan Online Judge

思路:

题目意思翻译:在递增的序列中找一段最大(子序列最小元素要比原序列中前一个大K+1以上)子序列满足(a[i]-a[i-1]<=k),求这个子序列的最大长度。(原题目意思:语文不好是真理解不清楚)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,k,a[100005];

int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	sort(a+1,a+1+n);
	int c1=1,ans=0;
	/*for(int i=1;i<=n;i++)cout<<a[i]<<' ';
	puts("");*/
	for(int i=n;i>=2;i--){
		if(abs(a[i]-a[i-1]<=k))c1++;
		else break;
	}
	ans+=c1;
	cout<<ans<<endl;
	return 0;
}

T5:可重排列

题目链接:可重排列 - 题目 - Daimayuan Online Judge

思路:

这个和输出全排序有得一拼,dfs(数据小),记得回溯嗷!

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

int n,a[15],s,vis[15];
int num[1005];
void dfs(int x){
	if(x==s+1){
		for(int i=1;i<=s;i++)printf("%d ",num[i]);
		putchar('\n');
		return;
	}
	for(int i=1;i<=n;i++){
		if(vis[i]==a[i])continue;
		vis[i]++;
		num[x]=i;
		dfs(x+1);
		vis[i]--;//回溯
	}
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),s+=a[i];
	dfs(1);

 	return 0;
}

T6:进制转换

题目链接:http://oj.daimayuan.top/course/11/problem/612

思路:模拟

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m;

long long con(string s,int jz){//将jz进制转化为十进制
	long long sum=0;
	int len=s.length();
	for(int i=0;i<len;i++){
		if(s[i]<='Z'&&s[i]>='A')sum=sum*jz+(s[i]-'A')+10;
		else if(s[i]>='a'&&s[i]<='z')sum=sum*jz+(s[i]-'a')+36;
		else sum=sum*jz+(s[i]-'0');
	}
	return sum;
}
void pr(long long x,int jz){
	string s;
	while(x!=0){
		int t=x%jz;
		string p;
        //char转string的操作,先定义,再赋值
		if(t>=10&&t<=35)p='A'+(t-10);
		else if(t>=36&&t<=61)p='a'+(t-36);
		else p='0'+t;
		s+=p;
		x/=jz;
	}
	reverse(s.begin(),s.end());//记得翻转一下
	cout<<s<<endl;
}
ll ans=0;
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>d[i].jz>>d[i].num;
	for(int i=1;i<=n;i++){
		ll now=con(d[i].num,d[i].jz);
		ans+=now;
	}
	pr(ans,m);

 	return 0;
}

T7:循环子串

题目链接:循环子串 - 题目 - Daimayuan Online Judge

思路:

按题意模拟即可,然后会用到string的三个函数:

  • substr(i,len)截取从下标i开始长度为len的字符串
  • reverse(i,j)翻转i到j的字符串
  • find(s)在字符串中查找s子串,若找到了返回s第一个字母出现的第一个下标,反之返回s.npos;
#include<bits/stdc++.h>
#define ll long long
using namespace std;

int t;
int main()
{
	cin>>t;
	while(t--){
		int n,f=1;string s;
		cin>>n>>s;
		s+=s;//由于需要循环k位,直接将s和s首尾相接
		for(int len=2;len<=n;len++){
			for(int i=0;i+len<n;i++){
				string now=s.substr(i,len);
				reverse(now.begin(),now.end());
				if(s.find(now)==s.npos){//在构造的s字符串中查找截取并翻转的字符串
					f=0;break;
				}
			}
			if(!f)break;
		}
		if(f)cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}


 	return 0;
}

T8:饿饿 饭饭之暑假大狂欢

题目链接:http://oj.daimayuan.top/course/11/problem/615

思路:

一个集合为{1,2,3},自己是{1,2,3,4},显然自己不能获胜,自己能不能获胜主要看别人是否为自己的子集问题,只有其他人全部都不是自己的子集,才能获胜。

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

int t,a[105][105];
vector<int> v[105];
int main()
{
	cin>>t;
	for(int i=1;i<=t;i++){
		int x,n;cin>>n;
		for(int j=1;j<=n;j++){
			cin>>x;
			v[i].push_back(x);
		}
	}
	for(int i=1;i<=t;i++){
		int cnt=0;
		for(int j=1;j<=t;j++){
			int f=0;
			if(i==j)continue;
			for(auto k:v[j]){
                //搜索别人是否为自己的子集
				if(find(v[i].begin(),v[i].end(),k)==v[i].end()){
					f=1;break;//只有不为子集的时候f才会为1
				}
			}
			if(f)cnt++;
		}
		if(cnt==t-1)cout<<"YES";//其余集合均不是自己的子集
		else cout<<"NO";
		puts("");
	}

 	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值