请注意:题目背景与题目可能没有关系
第一题,性质题,找到序列的最大值与最小值,我们发现如果只有正数的话和只有负数的话都很好处理,正数正序处理类似前缀加,负数后缀加,那如果正负都有,该怎么办呢?其实我们可以吧序列全变为正的或负的吧,但是需要比较一下最大值最小值,如果都变成正的话,对被卡掉,例如1 1 1 1 1 1 1 1 -1e9
就死了
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define pii pair<int,int>
using namespace std;
const int N = 1e5+5;
ll n,a[N],b[N];int cnt;
vector <pii> put;
void zh(int l,int r)
{
for(int i=l;i<r;i++)
{
if(a[i]<=a[i+1])continue;
a[i+1]+=a[i];
put.pb({i,i+1});
cnt++;
}
}
void fu(int l,int r)
{
for(int i=r;i>l;i--)
{
if(a[i]>=a[i-1])continue;
a[i-1]+=a[i];
put.pb({i,i-1});
cnt++;
}
}
int main()
{
speed();
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];b[i]=a[i];
}
sort(b+1,b+1+n);
if(b[1]>=0)
{
zh(1,n);
cout<<cnt<<endl;
for(auto [l,r]:put)
{
cout<<l<<" "<<r<<endl;
}
}else
{
if(b[n]<=0)
{
fu(1,n);
cout<<cnt<<endl;
for(auto [l,r]:put)
{
cout<<l<<" "<<r<<endl;
}
}
else
{
ll mx=b[n],pos=max_element(a+1,a+1+n)-a;
ll mi=b[1],pp=min_element(a+1,a+1+n)-a;
if(mx>-mi)
{
for(int i=n;i;i--)
{
int st=i;
while(a[st]<=0&&st>0)
{
a[st]+=mx;
put.pb({pos,st});
if(mx<a[st])
{
mx=a[st];
pos=st;
}
cnt++;
st--;
}
}
// for(int i=1;i<=n;i++)cout<<a[i]<<" ";
zh(1,n);
// for(int i=1;i<=n;i++)cout<<a[i]<<" "
cout<<cnt<<endl;
for(auto [l,r]:put)
{
cout<<l<<" "<<r<<endl;
}
}else
{
for(int i=n;i;i--)
{
int st=i;
while(a[st]>=0&&st>0)
{
a[st]+=mi;
put.pb({pp,st});
if(mi>a[st])
{
mi=a[st];
pp=st;
}
cnt++;
st--;
}
}
// for(int i=1;i<=n;i++)cout<<a[i]<<" ";
fu(1,n);
// for(int i=1;i<=n;i++)cout<<a[i]<<" "
cout<<cnt<<endl;
for(auto [l,r]:put)
{
cout<<l<<" "<<r<<endl;
}
}
}
}
// for(int i=1;i<n;i++)
// {
// if(a[i]>a[i+1])
// {
// cout<<i<<" "<<a[i]<<" "<<a[i+1]<<endl;
// cout<<"Wa"<<endl;
// return 0;
// }
// }
return 0;
}
这题,如果直接用暴力矩阵乘法的话是\(O(n^3)\),显然过不了,但我们可以发现一个性质,就是我们可以随机一个\(n\times 1\)矩阵,值得注意的是矩阵不满足交换律,但是\(randP \times A\times B \equiv randP\times C\)矩阵由\(n^2\)转换为\(n\)
这样我们就转换为\(O(n^2)\)的复杂度了
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const ll mod=998244353;
ll n;
mt19937 seed(random_device{}());
int rand(int l,int r)
{
uniform_int_distribution<int>range(l,r);
return range(seed);
}
struct Matrix
{
vector <vector<ll>> a;
int n,m;
Matrix(int _n,int _m):n(_n),m(_m)
{
a.resize(n+1,vector<ll>(m+1));
}
void resize(int n,int m)
{
a.resize(n+1,vector<ll>(m+1));
}
Matrix operator * (const Matrix& A)const
{
Matrix ans(n,1);
for(int i=1;i<=n;i++)
for(int j=1;j<=A.m;j++)
for(int k=1;k<=m;k++)
ans.a[i][j]=(ll)(ans.a[i][j]+(ll)a[i][k]*A.a[k][j]*1ll%mod)%mod;
return ans;
}
void T()
{
cout<<"******"<<endl;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
}
};
int main()
{
speed();
// freopen("sequence2.in","r",stdin);
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
int T;
cin>>T;
while(T--)
{
cin>>n;
Matrix A(n,n),B(n,n),C(n,n),b(n,1);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)cin>>A.a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)cin>>B.a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)cin>>C.a[i][j];
for(int i=1;i<=n;i++)
b.a[i][1]=rand(1,16);
// b.T();
C=C*b;
// C.T();
b=B*b;//这里注意啊,为什么这么写A*(B*b)=C*b
// b.T();
b=A*b;
// b.T();
bool f=1;
for(int i=1;i<=n;i++)
{
if(!f)break;
for(int j=1;j<=1;j++)
{
if(b.a[i][j]!=C.a[i][j])
{
f=0;break;
}
}
}
if(f)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
这题暴力分就是二维背包,考场上这都能写挂,挂了35分
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 1e4+5;
short n,A,B;short dp[N][N];
struct ac
{
short a,b;
}q[N];
int ans;
bool vis[N];
void dfs(int a,int b,int cnt)
{
if(a>A||b>B)
{
ans=max(ans,cnt);
return;
}
for(int i=1;i<=n;i++)
{
if(vis[i])continue;
vis[i]=1;
dfs(a+q[i].a,b+q[i].b,cnt+1);
vis[i]=0;
}
}
int main()
{
speed();
// freopen("construct2.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n>>A>>B;
short mx=0;
for(int i=1;i<=n;i++)
{
cin>>q[i].a>>q[i].b;
mx=max(q[i].a,mx);
mx=max(q[i].b,mx);
}
mx=max(mx,A);mx=max(mx,B);
// dfs(0,0,0);
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=mx;j>=q[i].a;j--)
{
for(int k=mx;k>=q[i].b;k--)
{
// if(j>=A&&j-q[i].a>=A)continue;
// if(k>=B&&k-q[i].b>=B)continue;
dp[j][k]=max<short>(dp[j][k],dp[j-q[i].a][k-q[i].b]+1);
// if(j>=A&&j-q[i].a>=A)continue;
// if(k>=B&&k-q[i].b>=B)continue;
ans=max<short>(ans,dp[j][k]);
// cout<<j<<" "<<k<<" "<<dp[j][k]<<endl;
}
}
}
// for(int i=0;i<=mx;i++)ans=max(ans,dp[A][i]);
// for(int i=0;i<=mx;i++)ans=max(ans,dp[i][B]);
cout<<dp[A][B]+(dp[A][B]!=n)<<endl;
return 0;
}
正解
考虑到\(O(nV^2)\)中\(V\)太大了,我们可以换一种枚举方式,换成\(f_{i,j,k}\)枚举前\(i\)人中选了\(j\)个人,\(A\)值为多少,复杂度为\(O(n^2V)\)这样就可以过了
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N = 1e4+5;
int n,A,B,dp[2][85][N];
struct ac
{
int a,b;
}q[N];
bool cmp(ac a,ac b)
{
return a.b<b.b;
}
int ans;
bool vis[N];
int main()
{
speed();
// freopen("construct2.in","r",stdin);
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
cin>>n>>A>>B;
int mx=0;
for(int i=1;i<=n;i++)
{
cin>>q[i].a>>q[i].b;
mx=max(q[i].a,mx);
mx=max(q[i].b,mx);
}
mx=max(mx,A);mx=max(mx,B);
memset(dp,0x3f,sizeof dp);
dp[0][0][0]=0;;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=i;j++)
{
for(int v=A;v>=0;v--)
{
dp[i&1][j][v]=dp[(i-1)&1][j][v];
if(j>=1&&v>=q[i].a)dp[i&1][j][v]=min(dp[i&1][j][v],dp[(i-1)&1][j-1][v-q[i].a]+q[i].b);
// cout<<dp[i][j][v]<<endl;
}
}
}
for(int j=1;j<=n;j++)
for(int v=A;v>=0;v--)
if(dp[n&1][j][v]<=B)ans=max(ans,j);
cout<<min(ans+1,n)<<endl;
return 0;
}