8.10 找规律+动态规划
-
- nowcoder训练
- 小q的数列
找规律,第一个答案很好算,第二个答案打表,发现是二进制里面一的个数减一
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 2e5 + 5;
string s;
vector<pair<int,int>>car(101);
int d=0;
int ex,ey;
int sx,sy;
int f[2];
int maxx(int a,int b,int c){
int cnt=max(a,b);
return max(cnt,c);
}
int ca(int x){
if(x==1){
return f[1];
}else if(x==0)return f[0];
return ca(x/2)+f[x%2];
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
f[1]=1;
f[0]=0;
int q=1;
cin >> q;
while (q--) {
int n;
cin>>n;
int ans=ca(n/2)+f[(n%2)];
int res=(1ll << ca(n)) - 1;
cout<<ans<<' '<<res<<'\n';
}
return 0;
}
- 魔法
建议偶尔回来看看多做,一个比较典的三维dp,状态转移方程如下
表示为消耗同次数下从两个方向转移过来,当次数大于 0 的时候还需要考虑从两个方向直接用魔法不消耗体力转移过来:
k最大为n+m ,即从一直使用魔法达到(n+m).
代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, h;
cin >> n >> m >> h;
vector a(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
cin >> a[i][j];
vector dp(n + 1, vector<vector<i64>>(m + 1, vector<i64>(n + m + 1)));
dp[1][1][0] = h;
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
for (int k = 0; k <= n + m; k ++) {
dp[i][j][k] = max({dp[i][j][k], dp[i - 1][j][k] - a[i][j], dp[i][j - 1][k] - a[i][j]});
if (k > 0) {
dp[i][j][k] = max({dp[i][j][k], dp[i - 1][j][k - 1], dp[i][j - 1][k - 1]});
}
}
}
}
i64 ans = 0;
for (int i = 0; i < n + m; i ++)
if (dp[n][m][i] > 0) {
ans = i;
break;
}
cout << ans << '\n';
return 0;
}