數論的一些黑科技
阿新 • • 發佈:2018-02-03
數論 problem ostream pro 暴力 width click https namespace
在【喬明達的省選專題】裏面有很多這樣的解題技巧:
把Σ*Σ類型的題O(n^2)轉化∑[n/i]∑[m/i],除法下結果相同的部分合並,復雜度降低至O(√n+√m)。當然論文裏的題型應該說說很經典了。這裏再積累幾個基礎題型。
1,求前n個正整數的約數之和,即∑=σ(i) ,(i=1到n)。其中n≤10^12。
把除法下結果相同的部分合並,前面累加和用等差公式求和,復雜度為O(√n) 。
通俗理解公式: for(i=1;i<=n;i++) ans=ans+有因子i的數的個數=ans+n / i; (其中n/i=|i*1|+|i*2|+...+|i*(n/i)|,表示i是多少個數的因子)
例題: A New Function 。代碼:
#include<cmath> #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; ll solve(int n) { ll ans=0; int B=sqrt(n); for(int i=2;i<=B;i++){ ansView Code+=(ll)(n/i-1)*i; //前面根號n個直接暴力,由於不要1和本身,所以這裏減一。 if(n/i>=B+1){ //後面合並商相同部分 ,L,R代表的是範圍(個數)。 ll L=B+1,R=n/i; ans+=(L+R)*(R-L+1)/2; } } return ans; } int main() { int T,n,Case=0; scanf("%d",&T); while(T--){ scanf("%d",&n); printf("Case %d: %lld\n",++Case,solve(n)); } return 0; }
2,求前n個正整數的莫比烏斯函數之和,即∑=u(i),其中n≤10^11
通俗理解公式:for(i=1;i<=n;i++) sum=sum+(u(1)+u(2)+u(3)+...u(j)) (其中,i*j<=n,表示以1到j為因子,i相同的合並)。
3,
數論的一些黑科技