6578 Blank
比赛的时候一下子想出来
O
(
n
4
)
O(n^4)
O(n4)
自己太蠢了,写的是有16常数的
O
(
n
4
)
O(n^4)
O(n4)
设
f
[
a
]
[
b
]
[
c
]
[
d
]
[
4
]
f[a][b][c][d][4]
f[a][b][c][d][4]为
a
=
i
a=i
a=i剩下三个为bcd时的方案数
没想到其实不用管最后一个是谁,开了
[
0...3
]
[0...3]
[0...3]记录
其实不用管最后一个是谁,并将abcd排序即可
时间复杂度
O
(
n
4
)
O(n^4)
O(n4),滚动数组空间复杂度
O
(
n
3
)
O(n^3)
O(n3)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,l,r) for(int i=l;i>=r;--i)
using namespace std;
typedef long long s64;
const int M=1e2+5;
const int mod=998244353;
int n,m;
int l[M],r[M],x_[M];
int f[2][M][M][M];
inline void inc(int &x,int y) {x+=y,x-=x>=mod?mod:0;}
int main() {
//freopen("a.txt","r",stdin);
int test_;
scanf("%d",&test_);
while (test_--) {
scanf("%d%d",&n,&m);
rep(i,1,m) scanf("%d%d%d",l+i,r+i,x_+i);
rep(i,1,m) {
rep(j,i+1,m) if(r[j]<r[i]) {
swap(r[i],r[j]);
swap(l[i],l[j]);
swap(x_[i],x_[j]);
}
}
f[0][0][0][0]=1;
int opt=0;
int head_=0;
rep(i,1,n) {
opt^=1;
rep(a,0,i-1) rep(b,0,a) rep(c,0,b) {
int num=f[opt^1][a][b][c];
f[opt^1][a][b][c]=0;
if(num) {
inc(f[opt][a][b][c],num);//0
inc(f[opt][i-1][b][c],num);//1
inc(f[opt][i-1][a][c],num); //2
inc(f[opt][i-1][a][b],num);//3
}
}
while (head_<m&&r[head_+1]==i) {
++head_;
rep(a,0,i) rep(b,0,a) rep(c,0,b) {
if(!f[opt][a][b][c]) continue;
int cnt=1;
cnt+=a>=l[head_];
cnt+=b>=l[head_];
cnt+=c>=l[head_];
if(cnt!=x_[head_]) f[opt][a][b][c]=0;
}
}
}
int ans=0;
rep(a,0,n) rep(b,0,a) rep(c,0,b) inc(ans,f[opt][a][b][c]);
cout<<ans<<endl;
memset(f[opt],0,sizeof(f[opt]));
}
}
6581 Vacation
二分答案+check
二分时间,算每个人到达的位置,满足i不能超过i+1即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,l,r) for(int i=l;i>=r;--i)
using namespace std;
typedef long long s64;
const int M=1e5+5;
int n;
int len[M],way[M],spe[M];
double dis[M];
bool check(double t) {
dis[n]=way[n]-spe[n]*t;
per(i,n-1,1) {
dis[i]=way[i]-spe[i]*t;
if(dis[i]<dis[i+1]+len[i+1]) dis[i]=dis[i+1]+len[i+1];
}
return dis[1]<0;
}
int main() {
//freopen("a.txt","r",stdin);
//freopen("c.out","w",stdout);
while (scanf("%d",&n)==1) {
++n;
rep(i,1,n) scanf("%d",len+i);
rep(i,1,n) scanf("%d",way+i);
rep(i,1,n) scanf("%d",spe+i);
double l=0,r=1e9,mid;
rep(i,1,100) {
mid=(l+r)*0.5;
if(check(mid)) r=mid;
else l=mid;
}
printf("%.10f\n",r);
}
}
6586 String
一开始看成子串。。。
贪心思路,顺次枚举第i个字母,check是否可行
显然从头开始选最靠前的字母
剩下的就要check
a
i
ϵ
[
l
i
,
r
i
]
a_ {i} \epsilon [l_{i},r_{i}]
aiϵ[li,ri]即可
细节一定要自己写对拍
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
//#include <bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,l,r) for(int i=l;i>=r;--i)
using namespace std;
typedef long long s64;
const int M=3e5+5;
int n;
int shu[30];
int sum[M][30];
int L[M],R[M],len;
int nxt[M][30];
char s[M];
bool check(int hav,int x) {
rep(i,0,25) if(shu[i]>R[i]) return 0;
rep(i,0,25) if(L[i]-shu[i]>sum[n][i]-sum[x-1][i]) return 0;
int tot=0;
rep(i,0,25) tot+=max(0,L[i]-shu[i]);
if(tot>len-hav) return 0;
tot=0;
rep(i,0,25) tot+=min(sum[n][i]-sum[x-1][i],R[i]-shu[i]);
return tot>=len-hav;
}
int main() {
// freopen("a.txt","r",stdin);
// freopen("c.out","w",stdout);
while (scanf("%s",s+1)==1) {
memset(shu,0,sizeof(shu));
scanf("%d",&len);
n=strlen(s+1);
rep(i,0,25) scanf("%d%d",L+i,R+i);
bool not_=0;
rep(i,0,25) {
if(L[i]>R[i]) not_=1;
}
if(not_) {
puts("-1");
continue;
}
int kkkk=0;
rep(i,0,25) kkkk+=R[i];
if(kkkk<len) {
puts("-1");
continue;
}
rep(i,1,n) {
rep(j,0,25) sum[i][j]=sum[i-1][j];
++sum[i][s[i]-'a'];
}
memset(nxt[n+1],0,sizeof(nxt[n+1]));
per(i,n,1) {
rep(j,0,25) nxt[i][j]=nxt[i+1][j];
nxt[i][s[i]-'a']=i;
}
bool vis=0;
rep(i,0,25) {
++shu[i];
if(nxt[1][i]&&check(1,nxt[1][i]+1)) {
vis=1;break;
}
--shu[i];
}
memset(shu,0,sizeof(shu));
if(!vis) puts("-1");
else {
int pre=1;
rep(i,1,len) {
rep(j,0,25) {
if(!nxt[pre][j]) continue;
++shu[j];
if(check(i,nxt[pre][j]+1)) {
putchar('a'+j);
pre=nxt[pre][j]+1;
break;
}
--shu[j];
}
}
puts("");
}
}
}