求个60分的代码可以吗qaq(我太弱了

P4933 大师

n≤100,v≤2000 从这里开始就需要DP了。 我们观察到值域很小,这提示我们把和值域相关的量记入状态表示。 用f(i,j)f(i,j)f(i,j)表示以位置i结尾,公差为j的等差数列有多少个。转移的时候,枚举一个小于i的k,满足hk=hi−jh_k = h_i - jhk​=hi​−j,然后从f(k,j)f(k,j)f(k,j)转移到f(i,j)f(i,j)f(i,j)。 注意,公差可以是负数,因此这里的j也可以是负数。 转移的时候要小心,不要重复或者遗漏某些情况。 复杂度O(n2k)O(n^2k)O(n2k)。
by 良辰、 @ 2019-02-12 17:23:43


思路十分明确(from:__stdcall)
by 良辰、 @ 2019-02-12 17:24:17


同求
by jor蛋 @ 2022-07-02 18:34:00


应该不是这样的60分吧? ```c #include<bits/stdc++.h> using namespace std; const int N=1e3+10,H=4e4+20,MOD=998244353,C=2e4+10; using ll = long long; int f[N][H],a[N]; int n; ll res; int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; for(int j=-2000;j<=2000;j++){ for(int i=1;i<=n;i++){ for(int k=1;k<i;k++){ if(a[i]-a[k]==j){ f[i][j+C]=(f[k][j+C]+f[i][j+C]+1)%MOD; res=(res+f[k][j+C]+1)%MOD; } } } } cout<<res+n; } ```
by jor蛋 @ 2022-07-02 19:46:21


这样? ```cpp #include <cstdio> #include <cstdlib> #include <algorithm> #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) using namespace std; typedef long long ll; int n; ll h[1005], dp[1005][40005], vmx = -0x3f3f3f3f, vmn = 0x3f3f3f3f; const ll M = 998244353LL; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%lld", h + i); vmx = max(vmx, h[i]); vmn = min(vmn, h[i]); } ll ans = n * 1LL; int df = vmx - vmn; for(int i = 1; i <= n; i++) for(ll j = vmn - vmx; j <= df; j++) { dp[i][j + df] = 1LL; for(int k = 1; k < i; k++) { if(h[k] == h[i] + j) dp[i][j + df] = (dp[i][j + df] % M + dp[k][j + df] % M) % M; } } for(int i = 1; i <= n; i++) for(ll j = vmn - vmx; j <= df; j++) ans = (ans % M + dp[i][j + df] % M - 1) % M; printf("%lld", ans); system("pause"); return 0; } ```
by __Remake__ @ 2022-08-29 03:13:36


|