A. 小智的疑惑
题目描述
传智专修学院给了小智一个仅包含小写字母的字符串 s,他想知道,里面出现了多少次子串 chuanzhi 呢。
我们称一个字符串 t 是 s 的子串,当且仅当将 s 的开头若干个(可以为 0 个)连续字符和结尾若干个(可以为 0 个)连续字符删去后,剩下的字符串和 t 相同。例如,我们称 ab 是 abc 的子串,但 ac 不是 abc 的子串。
解题思路: 直接开python,快速方便。
print (input().count('chuanzhi'))
B. 三元组
题目描述
给定一个长度为 n 的数列 a,对于一个有序整数三元组 (i,j,k),若其满足 1≤i≤j≤k≤n 并且 ai+aj=ak,则我们称这个三元组是「传智的」。
现在请你计算,有多少有序整数三元组是传智的。
解题思路: 暴力循环。
#include<bits/stdc++.h>
using namespace std;
int a[105],n,ans,t;
int main()
{
cin>>t;
while(t--)
{
ans=0;
cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
for(int i=0;i<n;i++)
{
for(int j=i;j<n;j++)
{
for(int k=j;k<n;k++)
{
if(a[i]+a[j]==a[k])ans++;
}
}
}
cout<<ans<<endl;
}
return 0;
}
C. 排排队
题目描述
在传智专修学院中,每个人都有一个身高 ai,并且只有相邻的两个人可以交换位置。小智带领的队伍有 n 个人,他现在要给大家排队形。
给定一个长度为 n 的序列 b,一个队形被认为美观,当且仅当对于所有的 i=1,2,3,…n,ai=bi。小智想知道,他能否让大家的队形变得美观,并且交换相邻两个人的次数不超过 n^2 次。这个问题把小智难住了,请你帮他来解决这个问题,如果存在合法的交换方案,输出 YES,并给出一组方案;否则,输出 NO。
解题思路: 重新对a进行排序然后交换位置,假设a={1,2,2,3},b={3,2,2,1},给多一个数组对当前的a确认位置num={4,2,3,1}代表最终要去到的位置,对num数字进行冒泡排序交换i和j的值最后变成{1,2,3,4}就可以了。
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int t,n,a[N],b[N],num[N],flag;
int main()
{
cin>>t;
while(t--)
{
flag=0;
memset(num,0,sizeof num);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(a[j]==b[i]&&num[j]==0)//确保每个都有对应
{
num[j]=i;
break;
}
}
}
for(int i=1;i<=n;i++)if(num[i]==0)flag=1;
if(flag)//数量对不上直接输出no
{
cout<<"NO"<<endl;
continue;
}
cout<<"YES"<<endl;
for(int i=1;i<n;i++)
{
for(int j=1;j<n;j++)
{
if(num[j]>num[j+1])
{
cout<<j<<" "<<j+1<<endl;
swap(num[j],num[j+1]);
}
}
}
cout<<"0 0"<<endl;
}
return 0;
}
D. 背单词的小智
题目描述
大概意思就是,n个单词分成k个区间,确保最大的区间价值最小。
对于样例二,分成两个区间,代价分别是1+4+9=14和16,最大价值为16是最优解。
解题思路: 二分最大值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k,a[100005],x;
bool pd(ll num)
{
ll ans=0,sum=0;
for(int i=1;i<=n;i++)
{
sum+=a[i];
if(sum+a[i+1]>num)sum=0,ans++;
}
if(sum>0)ans++;
if(ans>k)return false;
return true;
}
int main()
{
ll l=1,r=1e18;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>x,a[i]=x*x;
l=max(l,a[i]);
}
while(l<r)
{
ll mid=l+r>>1;
if(pd(mid))r=mid;
else l=mid+1;
}
cout<<l<<endl;
return 0;
}
E. 游戏
写不出来555
F1. 生活在树上(easy version)
题目描述
给出n个节点和m个查询,查询两个城市之间的权值异或和是否等于k。
题目确保了城市是一棵最小生成树。
解题思路: 首先我们要知道异或的性质
交换律: a ^ b ^ c = a ^ c ^ b
任何数于0异或为任何数 :0 ^ n = n
相同的数异或为0:n ^ n = 0
接着看样例一的图
城市1到城市4的其中一种异或就是1-3异或4-3,结果就是8 ^ 2 ^ 6 ^ 6,相当于城市1直接异或到城市4,也就是8 ^ 2,所以我们只需要判断最短路径上的异或是否等于k然后输出就好了。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=500005;
int n,m,a[N],x,y,nex[N*2],en[N*2],ans;
ull w[N*2],num[N],val;
bool pd[N];
void add(int x,int y,ull val)
{
en[ans]=y;
w[ans]=val;
nex[ans]=a[x];
a[x]=ans++;
}
void dfs(int cnt)
{
for(int i=a[cnt];i!=-1;i=nex[i])
{
int j=en[i];
if(!pd[j])
{
num[j]=num[cnt]^w[i];
pd[j]=1;
dfs(j);
pd[j]=0;
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)a[i]=-1;
for(int i=1;i<n;i++)
{
cin>>x>>y>>val;
add(x,y,val);
add(y,x,val);
}
pd[1]=1;
for(int i=a[1];i!=-1;i=nex[i])
{
num[en[i]]=w[i];
dfs(en[i]);
}
while(m--)
{
ull u,v;
cin>>u>>v>>val;
if(n==1)
{
cout<<"NO"<<endl;
continue;
}
if(u!=1&&v!=1)
{
if((num[u]^num[v])==val)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
else
{
if(u==1)
{
if(num[v]==val)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
else
{
if(num[u]==val)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
}
return 0;
}