题目描述
小美有一个数组,她希望删除k个元素,使得剩余的元素两两之间互为倍数关系。你能告诉小美有多少种删除方案吗?由于答案过大,请对10^9+7取模。
输入描述:
第一行输入两个整数 n,k(1≤k≤n≤10^3) 表示数组长度,删除的元素数量。 第二行输入 n 个整数表示数组 a(1≤a[i]≤10^9) 。保证给定的数组中不存在两个相等元素。
输出描述:
输出一个整数表示答案。
示例1
输入
6 4 1 4 2 3 6 7
输出
8
说明
方案1:删除1,4,2,7。方案2:删除1,4,3,7。方案3:删除1,3,6,7。方案4:删除4,2,3,6。
方案5:删除4,2,3,7。方案6:删除4,2,6,7。方案7:删除4,3,6,7。方案8:删除2,3,6,7。
思路:
首先^_^对数据进行判断...好,数据很大取模,long long 走起
接下来头脑风暴ing-_-.动态规划,找状态转移方程!想法如图所示;注意一点,题目保证了不会出现相等的元素,我在此过程中排序了,保证顺序是小到大,如果不这样做,可能会漏分(eg:1 3 4 2,我以4为堆,前三个中只剩下两个的分法是 1 4,就会把2 4这种情况给漏了,所以需要排序)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n,k,mod=1e9+7,a[20000],dp[2050][2050];
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i],dp[i][1]=1;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
if(a[i]%a[j]==0)
{
for(int h=2;h<=n-k;h++)
{
dp[i][h]+=dp[j][h-1];
dp[i][h]%=mod;
}
}
}
}
LL res=0;
for(int i=1;i<=n;i++)
{
res=(res+dp[i][n-k])%mod;
}
cout<<res<<endl;
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=n;j++)
// {
// cout<<dp[i][j]<<' ';
// }
// cout<<endl;
// }
}