C. Multiplicity

本文解析了CodeForces C题的解题思路,利用DP算法求解数组中满足特定条件的子串数量。通过预处理数组元素的因子,采用从小到大的排序策略,确保了子串中每个数字只被使用一次,避免重复计数。最终通过统计并取模得到答案。

链接

[http://codeforces.com/contest/1061/problem/C]

题意

给你一个数组,让你找有多少个子串(并非连续,但相对位置不能换),满足bi%i==0;

分析

dp,直接先把ai的所有因子抠出来,并从小到大排序(这个很重要),然后dp[i]表示到当前这个数字,子串
长度为i的有多少个,很显然长度为i的依赖于前面的数字长度为i-1的子串数量,所以dp[vec[i][j]]=(dp[vec[i][j]]+dp[vec[i][j]-1])%mod;
为什么从大的因子枚举,因为在一个子串里该数字只能用一次,不然会多出。最后统计并取模,看代码体会吧。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
vector<ll> vec[100010];
ll a[100010];
ll dp[1000010];
const ll mod=1e9+7;
int main(){
    int n;
    ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        for(int j=1;j*j<=a[i];j++){
            if(a[i]%j==0){
                vec[i].pb(j);
                if(j*j!=a[i]) vec[i].pb(a[i]/j);
            }
        }
        sort(vec[i].begin(),vec[i].end());
    }
    dp[0]=1;
    for(int i=0;i<n;i++){
        for(int j=vec[i].size()-1;j>=0;j--)
        {
            dp[vec[i][j]]=(dp[vec[i][j]]+dp[vec[i][j]-1])%mod;
        }
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
       ans=(ans+dp[i])%mod;
       ans%=mod; if(dp[i]==0) break;
    }
    cout<<ans<<endl;
    return 0;
}

转载于:https://www.cnblogs.com/mch5201314/p/10008592.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值