0%

思路讲解

因为方向是确定的,可以从前往后推导。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
for(int s=cnts-1;s>=0;--s){
for(int i=0;i<=N;++i){
for(int j=0;j<=N;++j){
if(danger[s][i][j]) continue; // danger,continue
bitset<15> bi(s);
// set<array<ll,2> > mas;
// for(int k=0;k<M;++k){if(bi[k]) mas.insert(ma[k]);}
for(int k=0;k<2;++k){
ll u=i+di[k],v=j+dj[k];
if(u<0 || u>N) continue;
if(v<0 || v>N) continue;
if(danger[s][u][v]) continue;
ll idx=-1;
for(int l=0;l<M;++l){
if(ma[l][0]==u && ma[l][1]==v && bi[l]){idx=l;break;}
}
if(idx!=-1){
if(danger[s-(1<<idx)][u][v]) continue;
dp[s-(1<<idx)][u][v]+=dp[s][i][j];
dp[s-(1<<idx)][u][v]%=mod;
}else{
dp[s][u][v]+=dp[s][i][j];
dp[s][u][v]%=mod;
}

}

}
}
}

AC代码

327ms

https://codeforces.com/gym/105229/my

心路历程(WA,TLE,MLE……)

TLE,set常数太大。

思路讲解

就是注意到那,这个如果确定了要面对什么经历,那么肯定是选择从大到小经历最好,现在的问题就在于怎么样求这个东西,以及怎么拼起来?

那么拼起来我们用的是cal函数,其会调用mp解决拼起来的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 其实逻辑是先搞后一半,因为公式是sumB1*k2+val2+val1,那么我们要最大化sumB1*k2+val2
// 直接搞最大化比较难,但是k比较小,可以记录不同k下的val,最大化这个val。

// 输入剩余值 和 总经历数 返回最大的sumB1*k2+val2
auto cal=[&](ll rem,ll sumB1)->ll{
ll res=0;
for(int i=1;i<=N;++i){
auto it=lower_bound(mp[i].begin(),mp[i].end(),(array<ll,2>){rem,INF});
if(it==mp[i].begin()){
continue;
}
it=prev(it);
ll val2=(*it)[1];
res=max(sumB1*i+val2,res);
}
return res;
};

AC代码

https://codeforces.com/gym/105229/my#

心路历程(WA,TLE,MLE……)

思路讲解

AC代码

心路历程(WA,TLE,MLE……)

思路讲解

AC代码

心路历程(WA,TLE,MLE……)

思路讲解

前两问用二分,贪心解决。

最后一问需要使用双指针+倍增法。

AC代码

https://www.matiji.net/exam/oj/submit-detail/13507760/29/4498/F16DA07A4D99E21DFFEF46BD18FF68AD

心路历程(WA,TLE,MLE……)

调了比较久,最后终于是调出来了。最重要的就是这个倍增的板子,需要从N+1开始遍历。

1
2
3
4
5
6
7
vector<vector<ll> > jump(N+5,vector<ll>(mx_k+2,0));
ROF(i,N+1,1){
jump[i][0]=i<=N?nextPos[i]+1:N+1;
FOR(j,1,mx_k){
jump[i][j]=jump[jump[i][j-1]][j-1];
}
}