C. Multiplicity (CF 523 Div.2)
阿新 • • 發佈:2018-11-28
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 */