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 二刷,还是不会....没看出来是背包问题
- 背包问题是组合问题的延伸,这里牵扯到给每个增加的值如何取值的问题,本质是组合问题.
- 关于为什么状态转移方程不是f[i-1][j-Get_Mod((n-i)*a,n)]的问题,eg j=0,但它仍可以由其他余数t变来,如果考虑j比Get_Mod()小,那f[i][0]取不到值.