C. Multiplicity (CF 523 Div.2)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37868325/article/details/84368248

https://mp.csdn.net/postedit/84366147

简单dp题,公式是很好推的就是暴力超时呀,其实每次找的都是第i个数的不超过i的因子x,dp的s数组统计的是左边到当前位置长度为x的个数,所以当前位置截至的长度为x的个数就是左面长度为x-1的个数,这个很好推,那么对于第i个数,就不要直接O(a[i])的循环了,用O(sqrt(a[i])),找因子,然后因为是跟左面的有关,x-1对应的个数不能是当前位置更新过的,所以只需要用两个数记录一下就可以。

代码:

#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
long long n,m,a[100005],ans,s[100005],t,l,ll;
int main()
{
    t=-11;
    scanf("%I64d",&n);
    s[0]=1;
    for(int i=1;i<=n;i++)
    {
        scanf("%I64d",&a[i]);
        m=min((int)sqrt(a[i]),i);
        for(int j=1;j<=m;j++)
        {
            if(a[i]%j==0)
            {
                if(a[i]/j<=i&&(a[i]/j)!=j)
                {
                    s[a[i]/j]+=s[(a[i]/j)-1];
                    s[a[i]/j]%=mod;
                    //cout<<(i&1)<<" !!!!  "<<s[i&1][a[i]/j]<<" "<<s[!(i&1)][j]<<" "<<s[!(i&1)][(a[i]/j)-1]<<endl;
                }
                if(t==j-1)
                {
                    ll=l;
                    l=s[j];
                    s[j]+=ll;
                    s[j]%=mod;

                }
                else
                {
                    l=s[j];
                    s[j]+=s[j-1];
                    s[j]%=mod;
                }
                t=j;

            }//cout<<i<<" "<<j<<" "<<s[j]<<endl;
        }
    }
    for(int i=1;i<=n;i++)
    {
        ans+=s[i];
        //cout<<i<<" "<<s[i]<<" "<<ans<<endl;
                ans%=mod;
    }
cout<<ans<<endl;
    return 0;
}
/*
4 4
2 1 3 1
*/

猜你喜欢

转载自blog.csdn.net/qq_37868325/article/details/84368248