A.有用的算法(*800)
判断两个条件是否都满足条件即可
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
long long a[1000010];
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int flag1=1,flag2=1;
for(int i=1;i<n;i++)
{
if(a[i]>a[i+1])
{
flag1=0;
break;
}
}
for(int i=1;i<n;i++)
{
if(a[i]<a[i+1])
{
flag2=0;
break;
}
}
if(flag1||flag2) cout<<"erfen is useful!";
else cout<<"bukeyi";
}
B.平衡数(*800)
用字符串表示,或者计算数位和都可行
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
string s;
cin>>t;
while(t--)
{
cin>>s;
if(s[0]-'0'+s[1]-'0'==s[2]-'0'+s[3]-'0') cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
C.三角形(*900)
计算几何,将要询问的点(xp,yp)的x坐标带入直线方程,如果得出的y<yp,说明点在直线之下。求出AB和BC的直线方程,带入P坐标,如果都满足上述条件,说明点在三角形内。如果yp<=0直接输出no。
#include<bits/stdc++.h>
using namespace std;
int main()
{
double xb,xc,yc,xp,yp;
cin>>xb>>xc>>yc;
cin>>xp>>yp;
int flag1=0,flag2=0;
if(yp<=0)
{
cout<<"no"<<endl;
return 0;
}
double k1=yc/xc;
if(k1*xp>yp) flag1=1;
double k2=yc/(xc-xb);
if(k2*(xp-xb)>yp) flag2=1;
if(flag1&&flag2) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
D.文稿修订(*1200)
考查:字符串的基本操作
难度不大,直接进行模拟即可,就是有点麻烦。可以用字符串的插入函数insert进行插入,会方便很多。提前记录NEUQ和小写neuq的各种形态,然后每次从字符串中截取4位,如果是一个独立的单词且是NEUQ,就insert;如果是小写,就记录答案。将更改的字符串存入vector中,最后一并输出。
#include<bits/stdc++.h>
using namespace std;
map<string,int>mp;
map<string,int>st;
vector<int>v;
vector<string>ans[100010];
int main()
{
int res=0;
string s,str;
mp.clear();
st.clear();
st["NEUQ"]=1;
mp["neuq"]=mp["Neuq"]=mp["nEuq"]=mp["neUq"]=mp["neuQ"]=mp["NEuq"]=mp["NeUq"]=mp["NeuQ"]=mp["nEUq"]=mp["nEuQ"]=mp["neUQ"]=mp["NEUq"]=mp["NEuQ"]=mp["NeUQ"]=mp["nEUQ"]=1;
int cnt=0;
while(s!="#")
{
cin>>s;
char ch=getchar();
if(s=="#") break;
int n=s.length();
v.clear();
for(int i=0;i<n;i++)
{
str=s.substr(i,4);
if(s.length()==4)
{
if(mp[str]) res++;
if(st[str]) s.insert(i,"WOW ");
}
}
ans[cnt].push_back(s);
if(ch=='\n') cnt++;
}
cout<<res<<endl;
for(int i=0;i<cnt;i++)
{
for(int j=0;j<ans[i].size();j++)
{
if(j==ans[i].size()-1) cout<<ans[i][j];
else cout<<ans[i][j]<<" ";
}
if(i!=cnt-1) cout<<endl;
}
}
E.减肥计划(*1300)
考查:枚举,DFS
由于值域巨大,01背包并不可行。注意到n只有10个,如果进行枚举的话,最差也只有10!中情况,1s足够算完。枚举所有可能的选择物品的顺序, 可以用DFS或者全排列函数,然后对每种情况取最大值。
#include<bits/stdc++.h>
using namespace std;
int x[15],y[15],z[15],w[15];
int n,num[15],a,b,c;
int main()
{
int ans=0,d,e,f,sum=0;
cin>>n>>a>>b>>c;
for(int i=1;i<=n;i++) cin>>x[i]>>y[i]>>z[i]>>w[i];
for(int i=1;i<=n;i++) num[i]=i;
do{
d=0,e=0,f=0,sum=0;
for(int i=1;i<=n;i++)
{
d+=x[num[i]],e+=y[num[i]],f+=z[num[i]];
if(d>a||e>b||f>c) break;
sum+=w[num[i]];
}
ans=max(ans,sum);
}while(next_permutation(num+1,num+n+1));
cout<<ans;
}
F.吃包子(*1200)
考查:前缀和,双指针
其实和acwing上的最长不包含重复数的连续区间很相近,稍稍修改一下就行了。不过由于每次输出的是肉包子的数量,即区间内1的个数,还需要提前处理一下区间前缀和。
#include<bits/stdc++.h>
using namespace std;
int mp[2];
int main()
{
int n,m,a[1000010],s[1000010];
mp[0]=mp[1]=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
s[0]=0;
for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
int i=1,j=1,ans=0;
for(i=1,j=1;i<=n;i++)
{
mp[a[i]]++;
while(mp[0]>m)
{
mp[a[j]]--;
j++;
}
ans=max(ans,s[i]-s[j-1]);
}
cout<<ans;
}
G.数字鉴定(*1400)
考查:差分,预处理
第一步要做的就是区间合并,因为在本题我们只需要进行查询操作,只需要对在区间的数打上标记就可以了,对一个范围内的所有数做标记,我们自然会想到差分,而且本题甚至不需要构建差分数组,直接在范围内随便加一个数就可以算作标记。
第二步就是进行预处理,我们可以直接对2~1e6中所有的数依次记录它们的倍数(1一定不满足要求,剩下的数直接暴力算,大概要算12970034次,不会超时),如果这个数的倍数在区间内,就打上标记。这样预处理完之后,我们就可以做到在O(1)的时间复杂度下进行查询。
由于暴力预处理之后运行时间会比较吃紧,需要尽可能地优化输入和输出。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,q,l,r,x;
int st[N],b[N],query[N];
void add(int l,int r)
{
b[l]+=1;
b[r+1]-=1;
}
void judge()
{
for(int i=2;i<=N-10;i++)
{
int cnt=1;
while(i*cnt<=N-10)
{
if(b[i*cnt]>0)
{
st[i]=1;
break;
}
cnt++;
}
}
}
int main()
{
memset(b,0,sizeof(b));
memset(st,0,sizeof(st));
memset(query,0,sizeof(query));
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&l,&r);
add(l,r);
}
for(int i=1;i<=N-10;i++) b[i]+=b[i-1];
judge();
while(q--)
{
cin>>x;
if(x==1)
{
printf("NO\n");
continue;
}
if(st[x]) printf("NO\n");
else printf("YES\n");
}
}
I.试题排版(*1400)
考查:计数类dp
可参考洛谷P1806
用f[j]表示难度总和为i时的方案数量,状态转移方程为f[j]+=f[j-i],即每次对于总和j的方案数=难度和为j-i的方案数,再加上难度为i的题目。也可以看作完全背包,因为题目的难度为不递减,可以相等的,如果将题目的难度看成背包的物品,那么物品是可以随便取的(如对于总难度为4,我们可以选择[2,2],即选择了两个难度为2的物品),所以按照完全背包的模板,j应该从i~m循环。如果题目难度只能递增,那么就是01背包,因为每个难度只可能被选到一次。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int m;
cin>>m;
vector<int>dp(m+1);
dp[0]=1;
for(int i=1;i<=m;i++)
for(int j=i;j<=m;j++)
dp[j]=(dp[j]+dp[j-i])%998244353;
cout<<dp[m];
}