1 条题解

  • 0
    @ 2025-8-24 22:40:43

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 卷王
    可惜没如果.

    搬运于2025-08-24 22:40:43,当前版本为作者最后更新于2023-03-31 21:19:46,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题目大意

    求满足和为 ssti=ti1+at_i=t_{i-1}+ati=ti1bt_i=t_{i-1}-b 的长度为 nn 的数列 tt 的方案数。

    思路

    首先,得确定大概方向:

    一提到方案数,你会想到什么?

    • 搜索(当然可以,只是会 T 到飞起)

    • 记忆化搜索(emmm,我暂时还没研究过,或许可以吧)

    • 大炮——dp!(此题正解)

    其次,冷静分析数据范围:

    看到题目里面的 n1000n \leq 1000,再看看空间范围就可以大概猜测:用 O(n2)O(n^2) 的时空复杂度。这就是本题最清晰的解法。

    然后,设计状态:

    我们发现只有 nn 这一个变量可以二重循环,因此,我们尝试进行每重循环的次数都和 nn 有关。但是即使这样,空间也有可能不够啊!后面的都是 10610^6 级以上的!怎么办?我们会想到取模。于是设 dpi,jdp_{i, j} 表示前 ii 项的和模 nn 等于 jj 时的方案数。

    最后,最重要的转移方程:

    关于取模的转移方程,我不细讲了,就看 RoMantic_Queue 大佬的吧。觉得他讲的详细些。

    在一些数学推导(其实这题也是个数学题)后,得到转移方程 dp[i][j]=(dp[i1][c(ja×i)]+dp[i1][c(j+b×i)])dp[i][j]=(dp[i-1][c(j-a×i)] + dp[i-1][c(j+b×i)]),其中 c(x)c(x) 表示 xxnn 取模的结果,注意负数。

    坑点:

    • 注意模数是 108+710^8 + 7

    • 注意转移方程里面的加减,别搞混了。

    代码奉上:

    //time:2023-04-01
    #include <bits/stdc++.h>
    using namespace std;
    #define mod 100000007
    typedef long long ll;
    int n, s, a, b;
    int dp[1007][1007];
    inline int c(int x) {
    	return (x % n + n) % n;
    }
    int main() {
    	cin >> n >> s >> a >> b;
    	dp[0][0] = 1;
    	for(int i = 1; i < n; i++)
    		for(int j = 0; j < n; j++)
    			dp[i][j] = (dp[i - 1][c(j - a * i)] + dp[i - 1][c(j + b * i)]) % mod;
    	cout << dp[n - 1][c(s)];
    	return 0;
    }
    
    • 1

    信息

    ID
    5929
    时间
    1000ms
    内存
    128MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者