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,状态转移方程如下
d p i , j , k = max ( d p i , j , k , d p i 1 , j , k a i , j , d p i , j 1 , k a i , j )

表示为消耗同次数下从两个方向转移过来,当次数大于 0 的时候还需要考虑从两个方向直接用魔法不消耗体力转移过来:

d p i , j , k = max ( d p i , j , k , d p i 1 , j , k 1 , d p i , j 1 , k 1 ) [ k > 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;
}
posted @ 2024-08-13 14:57  冬天的睡袋  阅读(8)  评论(0编辑  收藏  举报