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;
}