福建农林大学校赛(同步赛)_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ
A题:
题目大意:有四种颜色的材料:绿(a)、蓝(b)、紫(c)、金(d)
使用3个绿色的材料合成1个蓝色的材料。
使用3个蓝色的材料合成1个紫色的材料。
使用3个紫色的材料合成1个金色的材料。
特殊的是每次使用材料合成新材料的时候都会返还一个旧的材料
思路:我们可以按材料的大小顺序先后合成:绿->蓝->紫->金
//比如第一种绿色:
//我们可以开一个while循环(条件是a>=3)
//每一次a合成的时候a-=3
//每一次蓝色都+1
//a每次有返还1个所以a+=1;
//while(a>=3)
{
a-=3;
b+=1;
a+=1;
//}
其他颜色同理
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int main()
{
ll a,b,c,d;
//四种材料
cin>>a>>b>>c>>d;
//绿、蓝、紫、金
//注意:金色因为是最高等级所以是不可以合成的它只能变多
while(a>=3)
{
a-=3;
b+=1;
a+=1;
}
while(b>=3)
{
b-=3;
c+=1;
b+=1;
}
while(c>=3)
{
c-=3;
d+=1;
c+=1;
}
cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
}
B题:B题:
题目大意:给定一共数组a,现在你有k次操作,每一次操作你可以选择一个元素把这个元素除以它的一个质因子
//比如6,它的质因子有1,2,3,你可以除3变成2
//问k次操作下数组a元素的乘积最小是多少
//思路因为最后要把a数组的元素都*起来所以我们可以这样想
//元素相乘可以看成是他们的所有质因子拆分相乘比如4*6
//4的质因子:2,2
//6的因子:2,3
那么就是2*2*2*3
那比如k是2的时候我们只需要删掉前k大的质因子就可以了
排序:3,2,2,2
那删掉3,2就剩下:2*2=4
如果还不懂的话我们可以看一下样例:
k=3
//1 1 4 5 1 4
//1的质因子(这里1比较特殊我们直接看成1):1
//1的质因子:1
//4的质因子拆分:2,2
//5的质因子拆分:5
//1的质因子拆分:1
//4的质因子拆分:2,2
//这样全部的因子*就是=1*2*2*5*1*2*2
//从大到小排序:5,2,2,2,2,1,1
//删除前3大的质因子:5,2,2
//剩下:2,2,1,1,答案就是2*2*1*1=4
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int mod=1e9+7;
ll a[N];
vector<int>ans;//用来存放所有的质因子
void sum(ll x)
{
//分解x的所有质因子
for(int i=2;i<=x/i;i++)
{
if(x%i==0)
{
while(x%i==0)
{
x/=i;
ans.push_back(i);
}
}
}
if(x>1)
{
ans.push_back(x);
}
}
int main()
{
ll n,k;
cin>>n>>k;
ll tmp=1;
priority_queue<ll>q;//大根堆
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum(a[i]);
}
sort(ans.begin(),ans.end(),greater<int>());
for(int i=k;i<ans.size();i++)
{
tmp=tmp*ans[i]%mod;
}
cout<<tmp<<endl;
}
C题:
题目大意:给出一个n和一个长度为2*n的字符串,问字符串里面是否存在7z这给字符串
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int mod=1e9+7;
ll a[N];
vector<int>ans;//用来存放所有的质因子
int main()
{
ll n;
cin>>n;
string s;
cin>>s;
string tmp="7z";
if(s.find(tmp)!=string::npos)
{
cout<<"YES"<<endl;
}
else cout<<"NO"<<endl;
}
D题有空再补
E题:没啥好说的就是板子题求最大子矩阵和
但是在设置maxn的时候要1e18因为里面每个数字绝对值最大不超过1e9所有全部加起来可能超过
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+10;
const int mod=1e9+7;
ll a[N];
ll sum[N][N];
vector<int>ans;//用来存放所有的质因子
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll n,m,r,c;
cin>>n>>m>>r>>c;
//矩阵的行和列
//子矩阵的行和列数
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
ll x;
cin>>x;
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+x;
//初始化
}
}
ll maxn=-1e18;
for(int i=r;i<=n;i++)
{
for(int j=c;j<=m;j++)
{
ll tmp=sum[i][j]-sum[i-r][j]-sum[i][j-c]+sum[i-r][j-c];
maxn=max(maxn,tmp);
}
}
cout<<maxn<<endl;
}
G:题目大意:每个人都有一个外号
问给出一个人的名字输出他的外号
就是简单考map应用:把每一个武将的名字映射成外号就行
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int mod=1e9+7;
ll a[N];
vector<int>ans;//用来存放所有的质因子
int main()
{
string s;
cin>>s;
map<string,string>mp;
mp["XuSheng"]="DaBao";
mp["GanNing"]="DaGui";
mp["QuYi"]="BaiMa";
mp["HuangZhong"]="LaoBao";
cout<<mp[s]<<endl;
}
H题:这题挺巧妙的
题目大意:有三种豌豆AA,Aa,aa
你可以选择任意种豌豆,每一种豌豆有它自己的重量
//问怎么选可以让总重量最大
//但是这个题目有一个限制就是
//就是AA和aa不可以一起选择这样豌豆会变质(虽然题目是说相对顺序但是举个例子)
这样也算放在一起
那改怎么做捏?
其实豌豆一共有5种出现的情况
1.全部是AA
2.全部是aa
3.全部是Aa
4.只有AA和aa
5,AA,Aa,aa三种都有
我们可以知道前三种答案就是全部的总重量之和
第4种我们只需要让suma=Σweigh(AA);
sumb=Σweigh(aa)
答案就是max(suma,sumb)
比较麻烦的是第5种:
有Aa出现的话那AA和aa是有可能可以一起选的比如
那怎么做呢?
其实我们可以把Aa作为一个分界点在还没有出现Aa的时候我们就可以当作1,2,4的情况做
也是suma=Σweigh(AA);
sumb=Σweigh(aa)
当碰到Aa的时候我们累计答案res+=max(suma,sumb)+w[i](这个w[i]是Aa的重量),算完后suma
情况如下
和sumb都要重置成0,因为我们是一组一组算的
当然拉最后一个Aa后面的豌豆最后没有结束条件去累计答案那我们直接在循环外面加个res+=max(suma,sumb)就行
//注意这个时候不用加w[i]因为没有Aa了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll w[N];//豆子的重量
const int mod=1e9+7;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll n;
cin>>n;
//豌豆的个数
for(int i=1;i<=n;i++)
{
cin>>w[i];
}
ll suma=0,sumb=0;
ll res=0;
for(int i=1;i<=n;i++)
{
string s;
cin>>s;
if(s=="AA")suma+=w[i];
else if(s=="aa")sumb+=w[i];
else
{
//出现Aa这个时候可以累计答案了
res+=max(suma,sumb);//累计每一次的答案
res+=w[i];//加上Aa的重量
suma=sumb=0;//复原
}
}
res+=max(suma,sumb);//这个一定要加因为1,2,3,4的情况for循环是不会累计答案的
//以及5情况的最后一组因为没有Aa的结束情况也不会累加所以一定要加这个条件
cout<<res<<endl;
}
I题:题目大意构造一个序列让每个数gcd(i,a[i])都不是质数
我们先可以初始化a数组a[i]=i;
我们知道如果i是质数那gcd(a[i],i)是等于i的这样就会出现质数这个肯定不行那我们怎么办呢
其实只需要和a[i+1]交换一下就行
那最后一个怎么办呢我们最后一共只需要和a[i-1]交换就行
因为除了2,3外没有连续的质数
但是1,2,3这样的话a[n]和a[n-1]换完是可以的
1 3 2
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll n;
int a[N];
bool check(int x)
{
if(x==1)return false;
if(x==2)return true;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)return false;
}
return true;
}
int main()
{
cin>>n;
if(n==1){
cout<<"1";
return 0;
}
for(int i=1;i<=n;i++)a[i]=i;
for(int i=1;i<=n;i++)
{
if(check(i))
{
if(i+1<=n)swap(a[i],a[i+1]),i++;
else swap(a[i],a[i-1]);
}
}
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
return 0;
}