• [dp]牛牛与数组


    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 32768K,其他语言65536K
    64bit IO Format: %lld

    题目描述

    牛牛喜欢这样的数组:
    1:长度为n
    2:每一个数都在1到k之间
    3:对于任意连续的两个数A,B,A<=B 与(A % B != 0) 两个条件至少成立一个

    请问一共有多少满足条件的数组,对1e9+7取模

    输入描述:

    输入两个整数n,k

    1 ≤ n ≤ 10
    1 ≤ k ≤ 100000

    输出描述:

    输出一个整数
    示例1

    输入

    复制
    2 2

    输出

    复制
    3
    示例2

    输入

    复制
    9 1

    输出

    复制
    1
    示例3

    输入

    复制
    3 3

    输出

    复制
    15
    示例4

    输入

    复制
    2 1234

    输出

    1515011
     

    题意:求一个长度为n的数组,满足用1-k的数组成前一个小于等于后一个或后一个不是前一个的倍数的条件有多少种,模1e9+7

    思路:当前一个数小于等于后一个数时,即使后一个数是前一个数的倍数也是可以成立的(两个条件只需满足一个),但只有当前一个数大于后一个数且前一个数是后一个数的倍数时,此方案才不成立,注意到不成立的方案数条件更少,所以用总方案数减去不成立的方案数求解时更容易,故设dp[i][j]为当前长度为i的数组末尾是j的方案数,当数组长度为1时,k种数的方案数都为1种,当长度i大于等于2时,若要在末尾加入数j,则用i-1长度的数组从1到k的方案数之和减去i-1时大于j的j的倍数的方案数即使长度为i时末尾加入j的方案数,最后计算长度为n的数组从1到k的方案数之和即为答案,注意计算时要模1e9+7

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int amn=1e5,mod=1e9+7;
     5 int dp[15][amn];
     6 int main(){
     7     int n,k;
     8     ll s,s1,ans=0;
     9     ios::sync_with_stdio(0);
    10     cin>>n>>k;
    11     memset(dp,0,sizeof dp);
    12     for(int i=1;i<=k;i++)dp[1][i]=1;
    13     for(int i=2;i<=n;i++){
    14         s=0;
    15         for(int j=1;j<=k;j++)
    16             s=(s+dp[i-1][j])%mod;
    17         for(int j=1;j<=k;j++){
    18             s1=0;
    19             for(int l=j+j;l<=k;l+=j)
    20                 s1=(s1+dp[i-1][l])%mod;
    21             dp[i][j]+=(s-s1)%mod;
    22         }
    23         }
    24     for(int j=1;j<=k;j++)ans+=dp[n][j],ans%=mod;
    25     printf("%lld
    ",ans);
    26 }
  • 相关阅读:
    前插法创建带头节点的单链表
    利用Oracle数据库发送邮件
    关于如何给C#中的ListBox控件添加双击事件
    类似QQ表情的功能,包括动态绑定图片
    ASP.NET 缓存技术总结
    VS2008 快捷键大全
    Oracle 中union的用法
    C#找到Excel中的所有Sheetname的方法
    推荐一个学习XPath的网站
    Oracle游标使用大全
  • 原文地址:https://www.cnblogs.com/Railgun000/p/11285826.html
Copyright © 2020-2023  润新知