1. 程式人生 > >C. Multiplicity (CF 523 Div.2)

C. Multiplicity (CF 523 Div.2)

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
*/