• 牛牛与数组(DP)


    链接:https://ac.nowcoder.com/acm/problem/21738来源:牛客网

    题目描述

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

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

    输入描述:

    输入两个整数n,k

    1 ≤ n ≤ 10
    1 ≤ k ≤ 100000

    输出描述:

    输出一个整数

    具体思路:

    dp[i][j]表示前i个序列,第i个位j的时候的合法情况。

    如果是三层暴力的话,肯定会T,我们可以记录第二个for循环的总值,然后再去把不符合的情况给去掉。如果条件1,我们累加这个数前面的数就好了。

    对于条件2,我们先预处理出来每个数的倍数,然后再减去不合法的情况就可以了。

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 # define ll long long
     4 # define inf 0x3f3f3f3f
     5 const int maxn = 2e5+100;
     6 const int  N = 15;
     7 const int mod = 1e9+7;
     8 ll dp[N][maxn];
     9 vector<ll>sto[maxn];
    10 int main(){
    11 int n,k;
    12 scanf("%d %d",&n,&k);
    13 for(int i=1;i<=k;i++){
    14 dp[1][i]=1;
    15 }
    16 for(int i=1;i<=k;i++){
    17 for(int j=2;j*i<=k;j++){
    18 sto[i].push_back(i*j);
    19 }
    20 }
    21 for(int i=2;i<=n;i++){
    22 ll sum=0;
    23 for(int j=1;j<=k;j++){sum=(sum+dp[i-1][j])%mod;}
    24 ll tmp=0;
    25 for(int j=1;j<=k;j++){
    26 dp[i][j]=(dp[i-1][j]+tmp)%mod;
    27 tmp=(tmp+dp[i-1][j])%mod;
    28 ll ans=(sum-tmp+mod)%mod;// 把已经算过的情况给删除
    29 for(int w=0;w<sto[j].size();w++){
    30 ans=(ans-dp[i-1][sto[j][w]]+mod)%mod;
    31 }
    32 dp[i][j]=(dp[i][j]+ans)%mod;
    33 }
    34 }
    35 ll ans=0;
    36 for(int i=1;i<=k;i++){
    37 ans=(ans+dp[n][i])%mod;
    38 }
    39 printf("%lld
    ",ans);
    40 return 0;
    41 }
  • 相关阅读:
    vijosP1360-八数码问题
    android——卡片式布局
    android ——悬浮按钮及可交互提示
    android ——滑动菜单
    android ——Toolbar
    android ——多线程编程
    android ——调用摄像头拍照和相册
    android ——通知管理
    android——实现跨程序访问数据
    android——SQLite数据库存储(操作)
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10966724.html
Copyright © 2020-2023  润新知