AcWing 1214. 波动数列

原题链接

考察:背包dp

错误思路:

       f[i,j] j表示和

此思路必错,会MLE.

正确思路:

      需要转换式子.已知 x + x+d1 + x+d1 +d2+x+d1+d2+d3...=s 等价于 nx+(n-1)d1+(n-2)d2+.. = s. s与n已知,d在a与b徘徊,而x的范围太广,因此可以考虑用其他变量表达x即

nx = s-(n-1)d1-(n-2)d2...d的取值是a与b.s与后面的式子同余.因此可以不知道x的值的问题下转化为背包问题.

     注意只需要塞满n-1个物品即可.因为一共就n-1个di要取值

坑点:

      s可以取负值,因此注意余数要是正数

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 const int N = 1010,Mod = 100000007;
 7 int f[N][N];
 8 int Get_Mod(int n,int mod)
 9 {
10     return (n%mod+mod)%mod;
11 }
12 int main()
13 {
14     int n,s,a,b,t;
15     scanf("%d%d%d%d",&n,&s,&a,&b);
16     t = Get_Mod(s,n);
17     f[0][0] = 1;
18     for(int i=1;i<n;i++)
19         for(int j=0;j<n;j++)//不能只取到t,因为下面的等式余数范围不清楚
20             f[i][j] = (f[i-1][Get_Mod(j-(n-i)*a,n)]+f[i-1][Get_Mod(j+(n-i)*b,n)])%Mod;
21     printf("%d\n",f[n-1][t]);
22     return 0;
23 }

 

2021.2.24 二刷,还是不会....没看出来是背包问题

  1. 背包问题是组合问题的延伸,这里牵扯到给每个增加的值如何取值的问题,本质是组合问题.
  2. 关于为什么状态转移方程不是f[i-1][j-Get_Mod((n-i)*a,n)]的问题,eg j=0,但它仍可以由其他余数t变来,如果考虑j比Get_Mod()小,那f[i][0]取不到值.
posted @ 2021-02-08 13:46  acmloser  阅读(91)  评论(0编辑  收藏  举报