蓝桥杯 波动数列

参考了很多的博客
主要
参考1
参考2

问题描述   观察这个数列:   1 3 0 2 -1 1 -2 …

这个数列中后一项总是比前一项增加2或者减少3。

栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整数数列可能有多少种呢? 输入格式
  输入的第一行包含四个整数 n s a b,含义如前面说述。 输出格式
  输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以100000007的余数。 样例输入 4 10 2 3
样例输出 2 样例说明   这两个数列分别是2 4 1 3和7 4 1 -2。 数据规模和约定
  对于10%的数据,1<=n<=5,0<=s<=5,1<=a,b<=5;
  对于30%的数据,1<=n<=30,0<=s<=30,1<=a,b<=30;
  对于50%的数据,1<=n<=50,0<=s<=50,1<=a,b<=50;
  对于70%的数据,1<=n<=100,0<=s<=500,1<=a, b<=50;
  对于100%的数据,1<=n<=1000,-1,000,000,000<=s<=1,000,000,000,1<=a,
b<=1,000,000。 ————————————————

先用一把深搜解决,并不能实际解决问题

import java.util.Scanner;

/**
 * @Author susuper
 * @Date 2019/11/19 17:13
 * @description:
 */
public class bodong1119 {
    static int n,s,a,b,num;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        s = sc.nextInt();
        a = sc.nextInt();
        b = sc.nextInt();

        int maxV = s + n*b;  //可以递增的最多值
        for(int i = s-n*a;i<=maxV;i++ ){
            dfs(i,i,1);
        }
        System.out.println(num);
    }

    public static void dfs(int cur,int all,int len){  // 当前值  总大小  长度
        if(len==n){
            if(all == s){
                num++;
                num%=100000007;
                return;
            }
            else{
                return;
            }
        }
        dfs(cur+a,all+cur+a,len+1);  //下一个值要+a
        dfs(cur-b,all+cur-b,len+1);  //下一个值要-b
    }
}

使用dp,几乎不会~~

import java.util.Scanner;

/**
 * @Author susuper
 * @Date 2019/11/19 17:13
 * @description:
 * 参考了很多博客,看懂了这道题目,可以用dfs解,但是必然会无法满足一些要求,用dp转化为01背包问题解决
 * 刚开始学动态规划,写起来还是比较困难的,最近几天要恶补一下动态规划了qaq
 */
public class bodong1119 {
    final static int maxn = 1100;
    static int n,s,a,b,num;
    static int p = 0;
    static long dp[][] = new long[2][maxn*maxn];
    static long count = 0;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        s = sc.nextInt();
        a = sc.nextInt();
        b = sc.nextInt();
        num = n*(n-1)/2;  //计算有多少个+3或-2
        dp();
        sum();
        System.out.println(count);
    }
    public static void dp(){
        int i,j;
        dp[p][0] = 1;  //最开始的时候,只有一个体积为0的物品,可以放到容量为0的背包,背包方案数是0
        for(i =1;i<n;i++){
            p = 1-p;
            for( j = 0;j<=(i+1)*i/2;j++){
                if(i>j){  //当前背包放不下 比前一个大一个的物品  所以放前一个
                    dp[p][j] = dp[1-p][j];
                }else{
                    dp[p][j] = (dp[1-p][j] + dp[1-p][j-i]) % 100000007;
                }
            }
        }
    }

    public static void sum(){
        for(int i = 0;i<=num;i++){
            int temp = s - i*a+(num-i)*b;
            if(temp%n==0){
                count = (count+dp[p][i])%100000007;
            }
        }
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值