给出n和m的值,要求求出一个"特别数组"的数量,并对1e9+7取模
其实并没有什么其他好计算的办法,那么就想到动态规划能否解决问题,首先n和m的范围都在1000以内,那么代表支持O(n2logn)的时间复杂度,那么dp的第一维肯定是我们有多少个数,另外"特别数组"是所有数加起来是n的倍数,也就是说模n为0,那么第二维就可以设置成当前所有数加起来模n为多少
所以我们设dp[i][j],表示当前一共有i个数并且所有数加起来模n为j的数组的数量,那么在转移的时候可以枚举i与j和当前最后一个数是多少,最后一位数一定是i的倍数,所以我们可以用一个调和级数的时间复杂度去枚举它,最后答案即为dp[n][0]
转移方程为
        for(int i=1;i<=n;i++){
            for(int j=0;j<n;j++){//模n最大为n-1
                for(int k=i;k<=m;k+=i){//k表示最后一个数为多少,它一定是i的倍数
                    dp[i][j] += dp[i-1][(j-k%n+n)%n];//若前i-1个数模n为(j-k+n)%n,那么((j-k+n)%n+k)%n=j,枚举所有情况
                    dp[i][j] %= mod;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<n;j++)//模n最大为n-1
            {
                for(int p=i;p<=m;p+=i)//p表示最后一个数为多少,它一定是i的倍数
                {
                    dp[i][j]=(dp[i][j]+dp[i-1][(j-p%n+n)%n])%mod;//若前i-1个数模n为(j-p+n)%n,那么((j-p+n)%n+p)%n=j,枚举所有情况
                }
            }
        }
时间复杂度为O(n2logm)
AC
#include <iostream>
using namespace std;
const int mod = 1000000007;
long long dp[1100][1100];
int main() {
    int n, m;
    cin >> n >> m;
    dp[0][0] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < n; j++) {
            for (int p = i; p <= m; p += i) {
                dp[i][j] = (dp[i][j] + dp[i - 1][(j - p % n + n) % n]) % mod;
            }
        }
    }
    cout << dp[n][0] << endl;
    return 0;
}
mod = 1000000007
dp = [[0 for _ in range(1100)] for _ in range(1100)]
n, m = map(int, input().split())
dp[0][0] = 1
for i in range(1, n + 1):
    for j in range(n):
        for p in range(i, m + 1, i):
            dp[i][j] = (dp[i][j] + dp[i - 1][(j - p % n + n) % n]) % mod
print(dp[n][0])
import java.util.*;
class Main {
    static int n,m;
    static long mod=1000000007;
    static long[][] dp = new long[1100][1100];
    public static void main(String[] args)
    {
        Scanner sc=new Scanner(System.in);
        n=sc.nextInt();
        m=sc.nextInt();
        dp[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<n;j++)
            {
                for(int p=i;p<=m;p+=i)
                {
                    dp[i][j]=(dp[i][j]+dp[i-1][(j-p%n+n)%n])%mod;
                }
            }
        }
        System.out.println(dp[n][0]);
    }
}
        小红最近一直在学习数组,突然有了一个想法,他定义了一个“特别数组”,当且仅当满足以下三个条件:
现在给出n和m的值,请你求出满足条件的“特别数组”数量。由于答案可能过大,请对109+7取模。
两个正整数n和m,用空格隔开。
1≤n,m≤1000
特别数组的数量,答案对109+7取模。
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
3 5
输出
4
说明
[1,2,3],[4,2,3],[2,4,3],[5,4,3]共有以上四个好数组
In following contests: