一、题目大意:
二、解题思路:
(1): 所求的两个子序列必定以一个数为分割点。
(2): 左边的子序列必定以分割点或者左边的其中一个数为结尾,右边的子序列必定以分割点右边的其中一个数为起始。
三、代码:
#include
using namespace std;
const int MAX = 50000+5;
const int inf = 1 << 29;
int T;
int main()
{
int qian[MAX], hou[MAX], total1[MAX], total2[MAX];
int a[MAX];
cin >> T;
for(int i=0; i> n;
for(int j=0; j> a[j];
qian[0] = a[0];
for(int j=1; j=0; j--)
hou[j] = max(a[j], hou[j+1]+a[j]);
total1[0] = qian[0];
for(int j=1; j=0; j--)
total2[j] = max(total2[j+1], hou[j]);
int ans = -inf;
for(int j=0; j
三、 代码:
#include
using namespace std;
const int MAXV = 304;
const int MAXP = 34;
const int inf = 1 << 30;
int dp[MAXV][MAXP];
int m[MAXV][MAXV];
int a[MAXV];
int main()
{
int V, P;
cin >> V >> P;
for(int i=1; i<=V; i++)
cin >> a[i];
for(int i=0; i<=V; i++)
for(int j=0; j<=P; j++)
dp[i][j] = inf;
for(int i=1; i<=V; i++)
m[i][i] = 0;
for(int i=1; i<=V; i++)
for(int j=i+1; j<=V; j++)
m[i][j] = m[i][j-1] + a[j] - a[(i+j)/2];
for(int i=1; i<=V; i++)
dp[i][1] = m[1][i];
for(int i=2; i<=V; i++)
for(int j=1; j<=i; j++)
for(int k=1; k<=i-1; k++)
dp[i][j] = min(dp[i][j], dp[k][j-1]+m[k+1][i]);
cout << dp[V][P] << endl;
return 0;
}
会议状态转移、初态。题解略, 代码
#include
using namespace std;
const int MAXN = 1005;
int a[MAXN];
int main()
{
int n;
cin >> n;
for(int i=1; i<=n; i++)
cin >> a[i];
int dp[MAXN];
dp[1] = 1;
for(int i=2; i<=n; i++)
{
dp[i] = 1;
for(int j=1; j<=i-1; j++)
{
if(a[i] > a[j])
dp[i] = max(dp[i], dp[j]+1);
}
}
int ans = 0;
for(int i=1; i<=n; i++)
ans = max(ans, dp[i]);
cout << ans << endl;
return 0;
}
一、题目大意
二、解题思想
1、利用sum[i][j]
记录(i,j)
左上方所有的和,然后利用前缀和的思想快速求出某个矩阵的和。最后使用四重循环,但是超时。
2、使用压缩维度和动态规划思想。
(1)压缩维度
(2)动态规划:对任意一个横跨 [ i , j ] [i,j] [i,j]行的矩阵,我们使用 s u m O f L i n e sumOfLine sumOfLine快速将其压缩为一维,然后求这个一维数组的最大连续子序列和。任意两行组合的最大值即为最终答案。 O ( n 3 ) O(n^3) O(n3)
三、代码
#include
#include
using namespace std;
const int MAX = 105;
const int inf = 1 << 30;
int grad[MAX][MAX];
int sum_of_line[MAX][MAX];
int line[MAX];
int get_max_sequence(int n)
{
int dp[MAX];
dp[1] = line[1];
for(int i=2; i<=n; i++)
dp[i] = max(line[i], dp[i-1]+line[i]);
int res = -inf;
for(int i=1; i<=n; i++)
res = max(dp[i], res);
return res;
}
int main()
{
int n;
scanf("%d", &n);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d", &grad[i][j]);
// ---------------计算行前缀和-----------------------------
for(int j=1; j<=n; j++)
for(int i=1; i<=n; i++)
sum_of_line[i][j] = sum_of_line[i-1][j] + grad[i][j];
// --------------------------------------------------------------
int ans = -inf;
for(int r1=1; r1<=n; r1++)
{
for(int r2=r1; r2<=n; r2++)
{
for(int j=1; j<=n; j++)
line[j] = sum_of_line[r2][j] - sum_of_line[r1-1][j];
int line_max = get_max_sequence(n);
ans = max(line_max, ans);
}
}
cout << ans << endl;
return 0;
}
#include
using namespace std;
const int MAXT = 1005;
const int MAXN = 105;
int dp[2][MAXT];
int time[MAXN];
int value[MAXN];
int max(int a, int b)
{
if(a < b)
return b;
return a;
}
int main()
{
int T, M;
scanf("%d%d", &T, &M);
for(int i=1; i<=M; i++)
scanf("%d%d", &time[i], &value[i]);
for(int i=0; i<=T; i++)
dp[0][i] = 0;
for(int i=1; i<=M; i++)
{
for(int j=1; j<=T; j++)
{
if(j-time[i] >= 0)
dp[i%2][j] = max(dp[1-i%2][j], dp[1-i%2][j-time[i]] + value[i]);
else
dp[i%2][j] = dp[1-i%2][j];
}
}
printf("%d\n", dp[M%2][T]);
return 0;
}
基本dp,回忆状态转移,代码:
#include
using namespace std;
const int MAX = 205;
int dp[MAX][MAX];
int main()
{
string s1, s2;
while(cin >>s1 >> s2)
{
int l1 = s1.length();
int l2 = s2.length();
for(int i=0; i<=max(l1, l2); i++)
{
dp[0][i] = 0;
dp[i][0] = 0;
}
for(int i=1; i<=l1; i++)
{
for(int j=1; j<=l2; j++)
{
if(s1[i-1] == s2[j-1])
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
cout << dp[l1][l2] << endl;
}
return 0;
}
定义: d p [ i ] dp[i] dp[i],还剩 i i i块的吃法
代码:
#include
using namespace std;
typedef long long ll;
ll dp[25];
int main()
{
dp[1] = 1;
dp[2] = 2;
int N;
cin >> N;
for(int i=3; i<=N; i++)
dp[i] = dp[i-1]+dp[i-2];
cout << dp[N] << endl;
return 0;
}
一、题目大意
二、解题思想:
最优路线肯定以其中一个点为峰值点,因此求从左到右和从右到左的最长上升子序列
三、代码:
#include
using namespace std;
const int MAXN = 1005;
int dp1[MAXN];
int dp2[MAXN];
int main()
{
int n;
cin >> n;
int a[MAXN];
for(int i=1; i<=n; i++)
cin >> a[i];
dp1[1] = 1;
for(int i=2; i<=n; i++)
{
dp1[i] = 1;
for(int j=1; j=0; i--)
{
dp2[i] = 1;
for(int j=n; j>i; j--)
{
if(a[i] > a[j])
dp2[i] = max(dp2[i], dp2[j] + 1);
}
}
int ans = -1;
for(int i=1; i<=n; i++)
ans = max(ans, dp1[i] + dp2[i] - 1);
cout << ans << endl;
return 0;
}
一、题目大意
有两种货币US / Canada Dollor
, 每天给出两种货币的汇率,然后可以选择全部换或者不换,换的时候要缴纳0.03
的手续费(换之后),并且两位小数后的钱直接不要,刚开始时有1000 Canada Dollor
,问给出N
天的Canada Dollor
对US Dollor
的汇率,最后第N
天最多可以有多少Canada Dollor
。
二、解题思路
us dollor
, k = 0 k=0 k=0为第 i i i天最多可拥有的can dollor
.三、代码
#include
#include
#include
using namespace std;
const int MAXD = 366;
double dp[MAXD][2];
double a[MAXD];
int N;
double remove_cent(double x)
{
return floor(x * 100)*1.0 / 100;
}
int main()
{
while(cin >> N && N)
{
for(int i=1; i<=N; i++)
cin >> a[i]; // 指a[i] Canada dollor <----> 1 US dollor, 即换出的时候应该越小越好,换进的时候越大越好
dp[0][0] = 1000;
dp[0][1] = 0;
for(int i=1; i<=N; i++)
{
dp[i][0] = max(dp[i-1][0], remove_cent(dp[i-1][1]*a[i]*0.97));
dp[i][1] = max(dp[i-1][1], remove_cent(dp[i-1][0]/a[i]*0.97));
}
// cout << dp[N][0] << endl;
printf("%.2lf\n",dp[N][0]);
}
return 0;
}
三、代码
#include
#include
using namespace std;
typedef long long ll;
ll dp[25][25];
int get_num(int x, int y)
{
if(dp[x][y] >= 0)
return dp[x][y];
dp[x][y] = get_num(x+1, y) + get_num(x, y+1);
return dp[x][y];
}
int main()
{
int n, m;
cin >> n >> m;
memset(dp, -1, sizeof(dp));
for(int i=0; i<25; i++)
dp[n+1][i] = dp[i][m+1] = 0;
dp[n][m] = 1;
cout << get_num(1,1) << endl;
return 0;
}
三、代码
#include
#include
using namespace std;
const int MAXM = 105;
typedef long long ll;
ll dp[MAXM][MAXM];
int grad[MAXM][MAXM];
ll get_num(int x, int y)
{
if(dp[x][y] >= 0)
return dp[x][y];
dp[x][y] = grad[x][y] + max(get_num(x+1, y), get_num(x, y+1));
return dp[x][y];
}
int main()
{
int r, c;
int T;
cin >> T;
while(T--)
{
cin >> r >> c;
for(int i=1;i<=r; i++)
{
for(int j=1; j<=c; j++)
{
cin >> grad[i][j];
}
}
memset(dp, -1, sizeof(dp));
for(int i=0; i
三、代码
#include
#include
using namespace std;
const int MAXN = 25;
const int MAXT = 1005;
typedef long long ll;
ll dp[MAXN][MAXT];
int a[MAXN];
int main()
{
int n, t;
cin >> n >> t;
for(int i=1; i<=n; i++)
cin >> a[i];
for(int i=0; i<=t; i++)
dp[0][i] = 0;
dp[0][0] = 1;
for(int i=1; i<=n; i++)
{
for(int j=0; j<=t; j++)
{
if(j-a[i] >= 0)
{
dp[i][j] = dp[i-1][j] + dp[i-1][j-a[i]];
}
else
dp[i][j] = dp[i-1][j];
}
}
cout << dp[n][t] << endl;
return 0;
}
一、题目大意
二、解题思想
这里的 T T T实在太大了,如果直接用0-1背包
,会超时,这类题给出了倍数的概念,那么就要往取模上考虑了。
模k
等于 j j j的最大重量。三、代码
#include
using namespace std;
const int MAXM = 100+5;
const int inf = 1<<30;
typedef long long ll;
ll dp[MAXM][MAXM];
ll a[MAXM];
int main()
{
int n,k;
cin >> n >> k;
for(int i=1;i<=n; i++)
cin >> a[i];
for(int i=0; i
三、代码
#include
#include
using namespace std;
const int MAXN = 10005;
const int MAXK = 105;
int dp[MAXN][MAXK]; // dp[i][j]:前i个数模k是否能够等于j
int a[MAXN];
int main()
{
int n, k;
cin >> n >> k;
for(int i=1; i<=n; i++)
cin >> a[i];
for(int i=0; i
三、代码
#include
using namespace std;
const int MAXN = 1005;
int dp[MAXN];
int a[MAXN];
int main()
{
int n;
cin >> n;
for(int i=1; i<=n; i++)
cin >> a[i];
dp[1] = a[1];
for(int i=2; i<=n; i++)
{
dp[i] = a[i];
for(int j=1; j
一、题目大意
直接见题目
二、解题思路
(1)开始时必在一栋建筑物上。
(2)可以选择往左往右。
因此是求往左和往右的两个最长上升子序列。
三、代码
#include
using namespace std;
const int MAXN = 105;
int dp1[MAXN];
int dp2[MAXN];
int a[MAXN];
int main()
{
int T;
cin >> T;
while(T--)
{
int n;
cin >> n;
for(int i=1; i<=n; i++)
cin >> a[i];
dp1[1] = 1;
for(int i=2; i<=n; i++)
{
dp1[i] = 1;
for(int j=1; j=1; i--)
{
dp2[i] = 1;
for(int j=n; j>i; j--)
{
if(a[i] > a[j])
dp2[i] = max(dp2[j]+1, dp2[i]);
}
}
int ans = 0;
for(int i=1; i<=n; i++)
ans = max(ans, max(dp1[i], dp2[i]));
cout << ans << endl;
}
return 0;
}
一、题目大意
这里
二、解题思路
这是一个二维背包问题。
三、代码
#include
#include
#include
using namespace std;
int l,m,n,minn;
int A[105][2];
int f[1005][505];
int main()
{
scanf("%d %d %d",&m,&l,&n);
for(int i=1;i<=n;i++)
{
scanf("%d %d",&A[i][0],&A[i][1]);
}
for(int i=1;i<=n;i++)
{
for(int j=m;j>=A[i][0];j--)
{
for(int k=l;k>=A[i][1];k--)
{
f[j][k]=max(f[j][k],f[j-A[i][0]][k-A[i][1]]+1);
}
}
}
printf("%d ",f[m][l]);
for(int i=0;i<=l;i++)
{
if(f[m][i]==f[m][l])
{
minn=i;
break;
}
}
printf("%d",l-minn);
}
一、题目大意
二、解题思路
(1) 搜索法: 由于题中说明了只要任意一步走法不同,就是两种方法,那么基于此我们就能直接进行深搜。
(2) 动态规划: 待思考,可参看博客
三、代码
#include
using namespace std;
int flag[50][50];
int dir[3][2] = {{0,1},{0,-1},{1,0}};
int offset = 20;
int cnt;
void dfs(int x, int y, int t)
{
if(t == 0)
{
cnt++;
return;
}
for(int i=0; i<3; i++)
{
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(flag[nx][ny]) continue;
flag[nx][ny] = 1;
dfs(nx, ny, t-1);
flag[nx][ny] = 0;
}
return;
}
int main()
{
int n;
cin >> n;
cnt = 0;
flag[0][offset+0] = 1;
dfs(0, 0+offset, n);
cout << cnt << endl;
}
一、题目大意
二、解题思路
(1) 首先肯定会在一个地方开餐馆
(2)如果确定在此开餐馆,就要看两边如何开餐馆利润最大。
三、代码
#include
using namespace std;
const int MAXN = 1005;
int p[MAXN];
int m[MAXN];
int dp1[MAXN];
int dp2[MAXN];
int main()
{
int T;
cin >> T;
while(T--)
{
int n , k;
cin >> n >> k;
for(int i=1; i<=n; i++)
cin >> m[i];
for(int i=1; i<=n; i++)
cin >> p[i];
dp1[1] = p[1];
for(int i=2; i<=n; i++)
{
dp1[i] = p[i];
for(int j=1; j k)
{
dp1[i] = max(dp1[i], dp1[j]+p[i]);
}
}
}
dp2[n] = p[n];
for(int i=n-1; i>=1; i--)
{
dp2[i] = p[i];
for(int j=n; j>i; j--)
{
if(m[j]-m[i] > k)
{
dp2[i] = max(dp2[i], dp2[j]+p[i]);
}
}
}
int ans = 0;
for(int i=1; i<=n; i++)
ans = max(ans, dp1[i]+dp2[i]-p[i]);
cout << ans << endl;
}
return 0;
}
三、代码
#include
using namespace std;
int a[5] = {0, 10, 20, 50, 100};
int dp[1000+5];
int main()
{
int n;
cin >> n;
for(int i=0; i<=n; i++)
dp[i] = 0;
dp[0]=1;
for(int i=1; i<=4; i++)**加粗样式**
for(int j=a[i]; j<=n; j++)
dp[j] += dp[j-a[i]];
if(n==0)
cout << 0 << endl;
else
cout << dp[n] << endl;
}
三、代码
#include
#include
#include
using namespace std;
int dp[24][24];
char s1[24];
char s2[24];
int main()
{
scanf("%s%s", s1, s2);
int l1 = strlen(s1);
int l2 = strlen(s2);
for(int i=0; i<=max(l1, l2); i++)
dp[0][i] = dp[i][0] = 0;
dp[0][0] = 1;
int i=0;
while(s1[i++] == '*' )
dp[i][0] = 1;
for(int i=1; i<=l1; i++)
{
for(int j=1; j<=l2; j++)
{
if(s1[i-1]==s2[j-1] || s1[i-1] == '?')
dp[i][j] = dp[i-1][j-1];
else if(s1[i-1] != s2[j-1] && s1[i-1] == '*')
{
for(int k=0; k<=j; k++)
{
dp[i][j] |= dp[i-1][j-k];
}
}
else
dp[i][j] = 0;
}
}
if(dp[l1][l2])
cout << "matched" << endl;
else
cout << "not matched" << endl;
return 0;
}
三、代码
#include
using namespace std;
const int MAX = 25;
typedef long long ll;
ll dp[MAX][MAX];
int main()
{
int t;
cin >> t;
while(t--)
{
int m, n;
cin >> m >> n;
for(int i=0; i= i)
dp[i][j] = dp[i-1][j] + dp[i][j-i];
else
dp[i][j] = dp[i-1][j];
}
}
cout << dp[n][m] << endl;
}
return 0;
}
三、代码
#include
#include
using namespace std;
const int MAXN = 105;
const int inf = 1 << 30;
int grad[MAXN][MAXN];
int dp[MAXN][MAXN];
int N;
int dfs(int x, int y)
{
if(x > N || y > N)
return inf;
if(dp[x][y] >= 0)
return dp[x][y];
dp[x][y] = grad[x][y]+min(dfs(x+1,y), dfs(x, y+1));
return dp[x][y];
}
int main()
{
cin >> N;
for(int i=1; i<=N; i++)
for(int j=1; j<=N; j++)
cin >> grad[i][j];
memset(dp,-1,sizeof(dp));
dp[N][N] = grad[N][N];
cout << dfs(1, 1) << endl;
}
#include
using namespace std;
int dp[105][105];
int grad[105][105];
int main()
{
int N;
cin >> N;
for(int i=1; i<=N; i++)
for(int j=1; j<=i; j++)
cin >> grad[i][j];
for(int j=1; j<=N; j++)
dp[N][j] = grad[N][j];
for(int i=N-1; i>=1; i--)
{
for(int j=1; j<=i; j++)
{
dp[i][j] = max(dp[i+1][j], dp[i+1][j+1])+grad[i][j];
}
}
cout << dp[1][1] << endl;
return 0;
}
三、代码
#include
#include
using namespace std;
int dp[105][12];
const int inf = 1<<30;
int main()
{
int n, m;
while(cin >> n >> m)
{
for(int i=1; i<=n; i++)
dp[i][1] = i;
for(int j=0; j<=m; j++)
dp[0][j] = 0;
for(int i=1; i<=n; i++)
{
for(int j=2; j<=m; j++)
{
dp[i][j] = inf;
for(int k=1; k<=i; k++)
{
dp[i][j] = min(dp[i][j], max(dp[k-1][j-1],dp[i-k][j])+1);
}
}
}
cout << dp[n][m] << endl;
}
return 0;
}
三、代码
#include
#include
using namespace std;
const int MAXM = 100005;
int dp[MAXM], a[MAXM];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%d", &a[i]);
dp[1] = a[1];
dp[0] = 0;
for(int i=2; i<=n; i++)
dp[i] = max(dp[i-1], dp[i-2]+a[i]);
printf("%d\n", dp[n]);
}
return 0;
}
三、代码
#include
#include
using namespace std;
const int MAX = 1005;
int is_hui[MAX][MAX];
int dp[MAX];
int main()
{
int T;
cin >> T;
while(T--)
{
string s;
cin >> s;
int L = s.length();
memset(is_hui, 0, sizeof(is_hui));
for(int i=0; i
三、代码
#include
#include
using namespace std;
int dp[45][7];
int a[45];
int get_num(int s, int e)
{
int res = 0;
for(int i=s; i<=e; i++)
res = res*10 + a[i];
return res;
}
int main()
{
int n, k;
cin >> n >> k;
for(int i=1; i<=n; i++)
scanf("%1d", &a[i]);
for(int i=1; i<=n; i++)
dp[i][0] = get_num(1,i);
for(int i=2; i<=n; i++)
{
for(int j=1; j
三、代码
#include
#include
using namespace std;
const int MAXV = 20005;
int dp[MAXV];
int a[33];
int main()
{
int V;
cin >> V;
int n;
cin >> n;
for(int i=1; i<=n; i++)
cin >> a[i];
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i=1; i<=n; i++)
for(int j=V; j>=a[i]; j--)
dp[j] = dp[j] | dp[j-a[i]];
int ans = MAXV;
for(int i=V; i>=0; i--)
{
if(dp[i])
ans = min(ans, V-i);
}
cout << ans << endl;
return 0;
}
一、题目大意
二、解题思路
(WA):不可以认为先取最大,再去次大。
(AC): 同时模拟两个人行走。
三、代码
#include
#include
#include
using namespace std;
int n,i,j,tmp,k,l;
int puz[20][20], dp[20][20][20][20];
int main()
{
scanf("%d",&n);
while(scanf("%d%d%d", &i, &j, &tmp) && i)
puz[i][j] = tmp;
memset(dp, 0, sizeof(dp));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
for(int k=1; k<=n; k++)
{
for(int h=1; h<=n; h++)
{
int tmp1 = max(dp[i-1][j][k-1][h], dp[i-1][j][k][h-1]);
int tmp2 = max(dp[i][j-1][k-1][h], dp[i][j-1][k][h-1]);
if(i==k && j == h)
dp[i][j][k][h] = max(tmp1, tmp2) + puz[i][j];
else
dp[i][j][k][h] = max(tmp1, tmp2) + puz[i][j] + puz[k][h];
}
}
}
}
cout << dp[n][n][n][n] << endl;
return 0;
}
#include
#include
using namespace std;
const int MAX = 105;
int dp[MAX][MAX];
int grad[MAX][MAX];
int c, r;
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
int dfs(int x, int y)
{
if(dp[x][y] > 0)
return dp[x][y];
dp[x][y] = 1;
for(int i=0; i<4; i++)
{
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(x < 1 || x > c || y < 1 || y > r)
continue;
if(grad[nx][ny] > grad[x][y])
dp[x][y] = max(dp[x][y], dfs(nx, ny)+1);
}
return dp[x][y];
}
int main()
{
cin >> c >> r;
for(int i=1; i<=c; i++)
for(int j=1; j<=r; j++)
cin >> grad[i][j];
memset(dp, -1, sizeof(dp));
int ans = 0;
for(int i=1; i<=c; i++)
for(int j=1; j<=r; j++)
ans = max(ans, dfs(i,j));
cout << ans << endl;
}
题解
三、代码
#include
using namespace std;
const int maxn=705;
int dp[maxn];
int a[maxn];
int main()
{
int n;
cin >> n;
for(int i=1; i<=n; i++)
cin >> a[i];
dp[0]=0;
dp[1] = a[1];
dp[2] = a[1] + a[2];
for(int i=3; i<=n; i++)
dp[i] = max(max(dp[i-3]+a[i-1]+a[i],dp[i-2]+a[i]), dp[i-1]);
cout << dp[n] << endl;
return 0;
}
一、题目大意
长度为 L L L的0-1串,不包含 101 101 101和 111 111 111的子串有多少种
二、解题思路
#include
using namespace std;
const int mod = 2005;
int dp[1000000+6];
int main()
{
int n;
cin >> n;
dp[0]=1;
dp[1]=2;
dp[2]=4;
dp[3]=6;
for(int i=4; i<=n; i++)
dp[i] = (dp[i-1]+dp[i-3]+dp[i-4])%mod;
cout << dp[n] << endl;
return 0;
}
向上向右
或者向上向左
走的状态,这样的状态共( d p [ i − 1 ] − d p [ i − 2 ] dp[i-1]-dp[i-2] dp[i−1]−dp[i−2])个其中 d p [ i − 2 ] dp[i-2] dp[i−2]是指 i − 1 i-1 i−1步状态中三个方向都能走的状态(因为它是由 i − 2 i-2 i−2步中左右状态向上走转移过来的)。三、代码
#include
using namespace std;
int main()
{
int dp[1004];
int N;
dp[0]=1;
dp[1]=3;
dp[2]=7;
int n;
cin >> n;
for(int i=3; i<=n; i++)
dp[i] = (2*dp[i-1]+dp[i-2])%12345;
cout << dp[n] << endl;
}
三、代码
#include
using namespace std;
const int mod = 5000011;
int dp[100000+5];
int n,m;
int main()
{
cin >> n >> m;
dp[0]=1;
for(int i=1; i<=m; i++)
dp[i] = 1 + i;
for(int i=m+1; i<=n; i++)
dp[i] = (dp[i-1]+dp[i-m-1])%mod;
cout << dp[n] << endl;
}
二、解题思路