hiho一下第226周《Ctrl-C Ctrl-V》

版权声明:水平有限,博客中难免不少纰漏甚至严重错误,希望大家指正。同时撰写最大的目的也在于交流学习,而不在关注和传播。任重而道远,MrYx与您共勉。 https://blog.csdn.net/yexiaohhjk/article/details/83547957

题意:

题目链接

思路:

看完题意应该很快反应典型dp题目,但数据太大,一定有什么递推式转换成公式的规律。
所以先想出一个O(n^2)的动态规划做法,打一个表再找规律。
dp[i]表示i个操作最多a,分析一下发现最优解最后一步要么是直接a,要么是连续的cltr-v转移过来。
j表示连续jcltr-v操作后。
所以 dp[i] = max(dp[i-1]+1,dp[i-j-2] *(j+1))

打100个数的表可以明显发现当i>=13后,dp[i] = dp[i-5] *4
那么当 x*5 + i = n时有 dp[n] = dp[i] * 4^x
其中4^x可以用快速幂加速!

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll mod = 1000000007;
int dp[1010];

void init(int n){
   memset(dp,0,sizeof(dp));
   for(int i=1;i<=6;i++) dp[i] = i;
   for(int i=7;i<=n;i++){
     for(int j=1;j<=i-2;j++){
        dp[i] = max(dp[i],max(dp[i-1] + 1, dp[i-j-2]*(j+1)));
     }
   }
}


ll qmd(ll a,int b){
      ll sum = 1;
      while (b){
          if (b & 1){
             sum = (sum * a) % mod;
           }
       b /=2;
       a = a * a % mod;
    }
    return sum;
}

int main(){
   //init(100); //打卡发现规律 当i>=11时候,dp[i]=dp[i-5]*4
   init(30);
   ll n;
   while(~scanf("%lld",&n)){
      int x;
      for(int i=16;i<=25;i++){
         if((n- i)%5 ==0){
            x = i;break;
         }
      }
      printf("%lld\n",(dp[x]*qmd(4,(n-x)/5))%mod);
   }
}

猜你喜欢

转载自blog.csdn.net/yexiaohhjk/article/details/83547957