C.多重度(思考+ dp最適化)

https://codeforces.com/problemset/problem/1061/C


アイデア:

dp [i] [j]:最初のiとi番目の長さがjのシーケンスの数

dp [i] [j] + = dp [i-1] [j];最初のi、および現在のiは、終了長がjのシーケンス
ですif(a [i]%j == 0)dp [ i] [j] + = dp [i-1] [j-1];

O(n ^ 2)最適化。これは、a [i]のすべての長さjが満たされているわけではなく、その除数がすべて満たされているためです。これはO(sqrt)です

次に、転送は前処理のおおよその位置から転送されます。

たとえば、係数の1つが7の場合、全長6を追加します。

寸法が圧縮されているため、01バックパックの逆の順序に似ています。

大きなものから小さなものまでの要因を列挙します。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=3e6+100;
typedef long long LL;
LL mod=1e9+7;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL dp[maxn];
vector<LL>v[maxn];
void solve(LL id,LL num){///求num的所有因子(非质因子)
    for(LL i=1;i<=sqrt(num);i++){
        if(num%i==0){
            if(i*i==num){
                v[id].push_back(i);break;
            }
            else{
                v[id].push_back(i);
                v[id].push_back(num/i);
            }
        }
    }
    sort(v[id].begin(),v[id].end());
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n;cin>>n;
  for(LL i=1;i<=n;i++){
     LL x;cin>>x;
     solve(i,x);
  }
  ///dp[i][j]+=dp[i-1][j]; 前i个,且当前i为终点长度为j的序列
  ///if(a[i]%j==0) dp[i][j]+=dp[i-1][j-1];
  dp[0]=1;

  for(LL i=1;i<=n;i++){
     for(LL j=v[i].size()-1;j>=0;j--){
         dp[v[i][j]]=(dp[v[i][j]]%mod+dp[v[i][j]-1]%mod)%mod;

     }
  }
  LL ans=0;
  for(LL j=1;j<=n;j++){
    ans=(ans%mod+dp[j]%mod)%mod;
  }
  cout<<ans<<"\n";
return 0;
}

 

おすすめ

転載: blog.csdn.net/zstuyyyyccccbbbb/article/details/114680488