版权声明:水平有限,博客中难免不少纰漏甚至严重错误,希望大家指正。同时撰写最大的目的也在于交流学习,而不在关注和传播。任重而道远,MrYx与您共勉。 https://blog.csdn.net/yexiaohhjk/article/details/83547957
题意:
思路:
看完题意应该很快反应典型dp题目,但数据太大,一定有什么递推式转换成公式的规律。
所以先想出一个O(n^2)的动态规划做法,打一个表再找规律。
dp[i]表示i个操作最多a,分析一下发现最优解最后一步要么是直接a,要么是连续的cltr-v转移过来。
j
表示连续j
个cltr-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);
}
}