【ACM-ICPC 2018 南京賽區網絡預賽 J】Sum
阿新 • • 發佈:2018-09-05
ont bre for 2個 namespace 最小 esp 我們 nan
【鏈接】 我是鏈接,點我呀:)
【題意】
在這裏輸入題意
【題解】
線性篩求出每個數的最小質因子x
for 從1-n
對於i,它的最小質因子為x
考慮i=ab
如果i能被x^3整除
那麽這x怎麽分配給它的兩個因子a,b都不行,(都有一個因子會分配至少2個以上,那麽我們提出來一個x^2的話,a或b就能被x^2整除了)。所以ans[i] = 0
如果i能被x^2整除(先判斷x^3再判斷x^2這樣能保證x就只能被x^2整除),那麽ans[i] = ans[i/(x^2)]
因為這個x顯然只能分到兩邊去(a,b各分配一個,不能都分配到a或都分配到b)
所以答案和i/(x^2)的一樣.i/(x^2)有多少個答按a‘ b‘,那麽把a‘和b‘都各乘上x就ok
如果i只能被x整除
ans[i] = ans[i/x]*2
因為這個x有兩種可能,分到a或者b。
所以i/x的每種方案a‘,b‘。
加一個x乘在a‘或者b‘都能湊成i的方案.且乘1個x顯然不會讓它有平方因子。
ans[1]=1
然後按照上面的規則遞推就好
(再求個前綴和
【代碼】
/* N在const裏面,可以改動; 求出2..N之間的所有質數; 放在zsb數組裏面; 時間復雜度是O(N)的; 但是需要空間也是O(N)的; */ #include <bits/stdc++.h> using namespace std; const int N = 2e7; bool iszs[N + 10]; int mizs[N+10]; int ans[N+10]; vector <int> zsb; int main() { #ifdef LOCAL_DEFINE freopen("rush_in.txt", "r", stdin); #endif memset(iszs, true, sizeof iszs); for (int i = 2; i <= N; i++) { if (iszs[i]) zsb.push_back(i); int len = zsb.size(); for (int j = 0; j <= len - 1; j++) { int t = zsb[j]; if (i*t > N) break; iszs[i*t] = false; mizs[i*t] = t; if (i%t == 0) break; } } ans[1] = 1; for (int i = 2;i <= N;i++){ int t = mizs[i]; if (t<=1000 && (i%(t*t*t)==0)){ ans[i] = 0; }else if (t<=10000&&(i%(t*t)==0)){ ans[i] = ans[i/(t*t)]; }else { ans[i] = ans[i/t]*2; } } for (int i = 2;i <= N;i++) ans[i] +=ans[i-1]; int T; scanf("%d",&T); while (T--){ int n; scanf("%d",&n); printf("%d\n",ans[n]); } return 0; }
【ACM-ICPC 2018 南京賽區網絡預賽 J】Sum