A:
显然,面包一样,肉贵的优先做
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
int b,p,f,h,c;
cin>>b>>p>>f;
cin>>h>>c;
if(h<c)swap(h,c),swap(p,f);
int x=min(b/2,p);
b-=x*2;
int ans=x*h;
x=min(b/2,f);
ans+=x*c;
cout<<ans<<endl;
}
return 0;
}
B:
最多可2500次,把所有可以执行的操作都执行一遍,如果还不行,肯定就不行了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 50+7;
int a[M][M];
int x[M*M],y[M*M],sz;
int vs[M][M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>a[i][j];
bool f=true;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
{
if(a[i][j]==0)continue;
if(a[i+1][j]==1&&a[i][j+1]==1&&a[i+1][j+1]==1)
vs[i][j]=vs[i+1][j]=vs[i+1][j+1]=vs[i][j+1]=1,x[++sz]=i,y[sz]=j;
}
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
{
if(a[i][j])
{
if(!vs[i][j])f=false;
}
}
if(!f)cout<<-1<<endl;
else
{
cout<<sz<<endl;
for(int i=1;i<=sz;i++)cout<<x[i]<<" "<<y[i]<<endl;
}
return 0;
}
C:
刚开始把所有交叉口高度设为2,其余设为1.
发现:只有把两个交叉口中间的高度全提为1,才有可能使结果变小
花费少2个天然气管道,多nm-1个竖直管道,遍历取即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 2e5+7;
char s[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
ll n,a,b;
cin>>n>>a>>b;
cin>>(s+1);
ll nm=0;
ll ans=(n+1)*b+n*a;
for(int i=1;i<=n;i++)
{
if(s[i]=='0')
{
if(nm)
{
ans+=a*2+(nm+1)*b;
nm=0;
}
}
else nm++;
}
nm=0;bool f=false;
// cout<<ans<<endl;
for(int i=1;i<=n;i++)
{
if(s[i]=='1')
{
if(f&&nm)
{
// cout<<nm<<" - "<<endl;
if(-a*2+(nm-1)*b<0)
ans+=-a*2+(nm-1)*b;
}
f=true;
nm=0;
}
else nm++;
}
cout<<ans<<endl;
}
return 0;
}
D:
显然直接算好序列不好算。
我们用总序列个数减去ab其中一个不好的情况
ab其中一个不好等于:a不好+b不好-ab同时不好。
前两个很好算直接乘法原理。
第三个:
先把a排序,a中相同数字可以任意交换,在b中进行排序(a相同数字)。
如果b最终是升序,则存在a不好b不好的情况。
在a相同数字的情况下,且b相同数字,的区间,对可以任意交换。
也是乘法原理。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 3e5+7;
const int mod = 998244353 ;
struct node{
int a,b;
}p[M];
int a[M],b[M];
bool cmp(node a,node b)
{
return a.a<b.a;
}
ll fac[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
fac[0]=1;
for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;
for(int i=1;i<=n;i++)
cin>>a[i]>>b[i],p[i]=node{a[i],b[i]};
sort(a+1,a+1+n);
sort(b+1,b+1+n);
ll ans=0;//序列为坏的个数
ll tp=1;int pr=1;
for(int i=2;i<=n+1;i++)
{
if(a[i]!=a[i-1])
{
tp=fac[i-1-pr+1]*tp%mod;
pr=i;
}
}
pr=1;
ans=(ans+tp)%mod;
tp=1;
for(int i=2;i<=n+1;i++)
{
if(b[i]!=b[i-1])
{
tp=fac[i-1-pr+1]*tp%mod;
pr=i;
}
}
ans=(ans+tp)%mod;
//下面求ab同时为坏的情况
sort(p+1,p+1+n,cmp);
for(int i=1;i<=n;i++)b[i]=p[i].b;
pr=1;
for(int i=2;i<=n+1;i++)
{
if(p[i].a!=p[i-1].a)
{
sort(b+pr,b+i);
pr=i;
}
}
bool f=true;
for(int i=2;i<=n;i++)
if(b[i]<b[i-1])f=false;
// cout<<ans<<" -- "<<f<<endl;
if(f)
{
tp=1;pr=1;
for(int i=2;i<=n+1;i++)
{
// cout<<p[i].a<<" "<<b[i]<<"=== "<<endl;
if(p[i].a!=p[i-1].a)
{
int br=pr;
// cout<<br<<" "<<i<<endl;
for(int j=pr+1;j<=i;j++)
{
if(b[j]!=b[j-1]||j==i)
{
// cout<<j<<" == "<<br<<" "<<j-1-br+1<<endl;
tp=tp*fac[j-1-br+1]%mod;
br=j;
}
}
pr=i;
}
// cout<<tp<<" - "<<endl;
}
ans=(ans+mod-tp)%mod;
}
ans=(fac[n]-ans+mod)%mod;
cout<<ans<<endl;
return 0;
}