牛客(牛牛与数组 )
链接: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
输出描述:
输出一个整数
输出
1515011
#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<algorithm> #include<map> #include <math.h> using namespace std; typedef long long ll; //c(n,k)*c(m,k)*k! inline int read() { int x=0,f=1;char ch=getchar(); while(ch<\'0\'||ch>\'9\'){if(ch==\'-\')f=-1;ch=getchar();} while(ch>=\'0\'&&ch<=\'9\'){x=x*10+ch-\'0\';ch=getchar();} return x*f; } const int maxn=1e5+10; const int mod=1e9+7; int dp[20][maxn]; int main(){ int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ dp[1][i]=1; } for(int i=2;i<=n;i++){ int sum=0; for(int j=1;j<=m;j++){ sum=(sum+dp[i-1][j])%mod; } for(int j=1;j<=m;j++){ int sum1=0; for(int k=j+j;k<=m;k+=j){ sum1=(sum1+dp[i-1][k])%mod; } dp[i][j]+=(sum-sum1)%mod; } } ll ans=0; for(int j=1;j<=m;j++){ ans+=dp[n][j]; ans%=mod; } printf("%lld",ans); } /* 题意:求一个长度为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 */