n%i之和
題目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1168
?
?
題意:給定一個n,注意這里n小于10^12,求
?
分析:早些時候就做過一道題,在這里:http://blog.csdn.net/acdreamers/article/details/8809517
由于當時這題數據小,直接計算步長更方便,但是對于本題由于10^12就不合適了,那么我們就采用第二種方法,現
在我就分別簡略說說這兩種方法,其實大體思路差不多,只是處理不一樣。
?
首先是不可能直接枚舉的,那么我們先把寫成,所以問題變為求:
?
由于在一定范圍內是保持不變的,所以我們接下來可以把時間復雜度降到
?
現在我們簡略模擬一下:比如n=30,那么我們可以劃分等價類:
?
?
可以看出,我們第一個和最后一個組合,第二個和倒數第二個組合,等等,如此進行下去,注意如果是奇數項,中間的那個只被加一次,這樣我們只需要枚舉到就行了。這個方法很好,其實還有一個相對還算可以方法,那么就是
記錄每個等價類的首元素和尾元素,每次跳一段長度,這樣對于10^9數據完全沒有問題。
?
本題由于數據很大,所以用Java大數:
import java.math.BigInteger; import java.util.Scanner; import java.math.*;public class Main {public static BigInteger Solve(long n){BigInteger ans=BigInteger.ZERO;long i,t=(long) Math.sqrt(n*1.0);for(i=1L;i<=t;i++){BigInteger a=BigInteger.valueOf(n/i+n/(i+1)+1); BigInteger b=BigInteger.valueOf(n/i-n/(i+1));BigInteger temp=BigInteger.ZERO;if(i!=(n/i))temp= (a.multiply(b)).divide(BigInteger.valueOf(2));BigInteger c=BigInteger.valueOf(n/i);BigInteger ret=c.add(temp);ret=ret.multiply(BigInteger.valueOf(i));ans=ans.add(ret);}return ans;}public static void main(String[] args){Scanner cin = new Scanner(System.in);while(cin.hasNextLong()){long n=cin.nextLong();BigInteger x=BigInteger.valueOf(n);System.out.println((x.multiply(x)).subtract(Solve(n)));}} }
?
總結
- 上一篇: NKU两题简单题解析(递归分析与位运算技
- 下一篇: Struts2概述