试题A:裁纸刀(AC)
题解代码:(答案443)
#include<bits/stdc++.h>
using namespace std;
int main()
{
int ans=4;
ans+=19;
ans+=20*21;
cout<<ans;
return 0;
}
试题B:灭鼠先锋(AC)
题解代码:(答案LLLV)
#include<bits/stdc++.h>
using namespace std;
bool failure(string s) //判断是否是只剩一个0的必败态
{
int count=0;
for(int i=0;i<8;i++){
if(s[i]=='O') count++;
}
if(count==1) return true;
else return false;
}
unordered_map<string, bool> SF;
bool dfs(string s)
{
if(SF.count(s)) return SF[s];
if(failure(s)) return SF[s]=false;
for(int i=0;i<s.size();i++){ //下一个棋子
if(s[i]=='O'){
string tmp=s;
tmp[i]='X';
if(!dfs(tmp))
return SF[s]=true; //下了这个棋子以后变为必败态,说明此时s是必胜态
}
}
for(int i=0;i<s.size()-1;i++){ //下两个棋子
if(s[i]=='O'&&s[i+1]=='O'&&i!=3){
string tmp=s;
tmp[i]=tmp[i+1]='X';
if(!dfs(tmp))
return SF[s]=true;
}
}
return SF[s]=false; //到这说明无论怎么下都会变成必胜态,则此为必败态
}
int main()
{
string s[]={"XOOOOOOO","XXOOOOOO","OXOOOOOO","OXXOOOOO"};
for(int i=0;i<4;i++)
{
if(dfs(s[i])) cout<<"L"; //如果当前态为必胜态,则小蓝输
else cout<<"V";
}
return 0;
}
试题C:求和(AC)
题解代码:
#include<bits/stdc++.h>
using namespace std;
long long a[200005];
long long pre[200005];
int main()
{
int n;
cin>>n;
long long ans=0;
for(int i=1;i<=n;i++){
cin>>a[i];
pre[i]=pre[i-1]+a[i];
}
for(int i=1;i<=n-1;i++){
ans+=a[i]*(pre[n]-pre[i]);
}
cout<<ans;
return 0;
}
试题D:选数异或(AC)
题解代码:
#include<bits/stdc++.h>
using namespace std;
int f[100005]; //f[i]=j表示以i为区间右边界时,j是满足条件的最大左边界
const int length=1<<20;
int last[length]; //last[i]表示i上一次出现的位置
int main()
{
int n,m,x;
cin>>n>>m>>x;
for(int i=1;i<=n;i++){
int a;
cin>>a;
f[i]=max(f[i-1],last[a^x]);
last[a]=i;
}
for(int i=1;i<=m;i++){
int l,r;
cin>>l>>r;
if(l<=f[r]) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}
线段树?
试题E:爬树的甲壳虫(AC)
题解代码:
#include<bits/stdc++.h>
typedef long long ll;
int MOD = 998244353;
ll x[100005], y[100005];
using namespace std;
// 使用广义欧几里得算法计算a和b的最大公因数,并求出x和y使得ax+by=gcd(a,b)
ll extended_gcd(ll a,ll b,ll &x,ll &y){
if (b==0) {
x=1;
y=0;
return a; // 返回最大公因数
}
ll x1, y1;
ll gcd=extended_gcd(b,a%b,x1,y1);
x=y1;
y=x1-(a/b)*y1;
return gcd;
}
// 计算a在模m下的逆元
ll modular_inverse(ll a,ll m){
ll x,y;
ll gcd=extended_gcd(a,m,x,y);
// 计算逆元并将其标准化到[0, m)范围内
ll inverse=(x%m+m)%m;
return inverse;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i];
ll g=__gcd(x[i],y[i]);
x[i]=x[i]/g;
y[i]=y[i]/g;
}
ll a=0,b=0;
for(int i=n;i>=1;i--){
ll p=x[i]*modular_inverse(y[i],MOD)%MOD;
ll p_1=(y[i]-x[i])*modular_inverse(y[i],MOD)%MOD;
a=(p+p_1*a)%MOD;
b=(1+p_1*b)%MOD;
}
a=modular_inverse(a-1,MOD);
int ans=MOD-b*a%MOD;
cout<<ans;
return 0;
}
试题F:青蛙过河(AC)
题解代码:
#include<bits/stdc++.h>
using namespace std;
long long h[100005];
long long pre[100005];
int main()
{
int n;
long long x;
cin>>n>>x;
x*=2;
for(int i=1;i<=n-1;i++){
cin>>h[i];
pre[i]=pre[i-1]+h[i];
}
int l=1;
int r=n-1;
int mid=(l+r)/2;
int ans=n;
while(1){
int length=mid;
bool flag=true;
for(int i=1;i<=n-length;i++){
int j=i+length-1;
long long sum=0;
sum=pre[j]-pre[i-1];
if(sum<x){
flag=false;
break;
}
}
if(flag==true){
ans=mid;
r=mid-1;
mid=(l+r)/2;
}
else{
l=mid+1;
mid=(l+r)/2;
}
if(l>r) break;
}
cout<<ans;
return 0;
}
试题G:最长不下降子序列(52分题解)
题解代码:
#include<bits/stdc++.h>
using namespace std;
int a[100005];
int dp1[100005];
int dp2[100005];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,k;
cin>>n>>k;
if(n<=k){
cout<<n;
return 0;
}
for(int i=1;i<=n;i++){
cin>>a[i];
dp1[i]=1;
dp2[i]=1;
}
for(int i=2;i<=n;i++){
for(int j=1;j<=i-1;j++){
if(a[i]>=a[j]){
dp1[i]=max(dp1[i],dp1[j]+1);
}
}
}
for(int i=n-1;i>=1;i--){
for(int j=i+1;j<=n;j++){
if(a[i]<=a[j]){
dp2[i]=max(dp2[i],dp2[j]+1);
}
}
}
int ans=k;
for(int i=k+1;i<=n-1;i++){
int lm=0;
for(int j=1;j<=i-k;j++){
if(a[j]<=a[i+1]){
lm=max(lm,dp1[j]);
}
}
ans=max(ans,lm+k+dp2[i+1]);
}
int sp1=k+dp2[k+1];
ans=max(ans,sp1);
int spm=0;
for(int i=1;i<=n-k;i++){
spm=max(spm,dp1[i]);
}
int sp2=spm+k;
ans=max(ans,sp2);
cout<<ans;
return 0;
}
线段树?