2018ACM-ICPC南京賽區網路賽: J. Sum(積性函式字首和)
J. Sum
A square-free integer is an integer which is indivisible by any square number except 11. For example, 6 = 2 \cdot 36=2⋅3 is square-free, but 12 = 2^2 \cdot 312=22⋅3 is not, because 2^222 is a square number. Some integers could be decomposed into product of two square-free integers, there may be more than one decomposition ways. For example, 6 = 1\cdot 6=6 \cdot 1=2\cdot 3=3\cdot 2, n=ab6=1⋅6=6⋅1=2⋅3=3⋅2,n=ab and n=ban=ba are considered different if a \not = ba̸=b. f(n)f(n) is the number of decomposition ways that n=abn=ab such that aa and bb are square-free integers. The problem is calculating \sum_{i = 1}^nf(i)∑i=1nf(i).
Input
The first line contains an integer T(T\le 20)T(T≤20), denoting the number of test cases.
For each test case, there first line has a integer n(n \le 2\cdot 10^7)n(n≤2⋅107).
Output
For each test case, print the answer \sum_{i = 1}^n f(i)∑i=1nf(i).
Hint
\sum_{i = 1}^8 f(i)=f(1)+ \cdots +f(8)∑i=18f(i)=f(1)+⋯+f(8)
=1+2+2+1+2+4+2+0=14=1+2+2+1+2+4+2+0=14.
題意:
令F(i)表示滿足x*y=i,且x和y都不包含平方數因子的合法(x,y)對數,求∑F(i)
思路:
很容易證明F(i)是積性函式,如果i中不存在3次方以上的質因子,F(i) = 2^(i中只出現一次的質因子個數),否則F(i) = 0
那麼就是個積性函式字首和的問題了
很多項都為0,利用Min_25篩可以在1s內輕鬆解決範圍內的所有詢問
#include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<string> #include<math.h> #include<queue> #include<stack> #include<iostream> using namespace std; #define LL long long #define mod 1000000007 #define er 500000004 int cnt, s[200005], id[200005], B, m, h[200005]; bool flag[200005]; LL n, w[200005], pri[200005]; void Primeset(int n) { int i, j; for(i=2;i<=n;i++) { if(flag[i]==0) { pri[++cnt] = i; s[cnt] = s[cnt-1]+i; } for(j=1;j<=cnt&&i*pri[j]<=n;j++) { flag[i*pri[j]] = 1; if(i%pri[j]==0) break; } } } LL F(LL x, int y) { LL t1; int i, k, e, ans; if(x<=1 || pri[y]>x) return 0; if(x>B) k = n/x; if(x<=B) k = id[x]; ans = 2*(h[k]-(y-1)); for(i=y;i<=cnt&&(LL)pri[i]*pri[i]<=x;i++) { t1 = pri[i]; for(e=1;t1*pri[i]<=x;e++) { if(e==1) ans = (ans+(F(x/t1, i+1)*2+1)); else if(e==2) ans = (ans+F(x/t1, i+1)); t1 *= pri[i]; } } return ans; } int main(void) { LL i, j, k, last; int T; scanf("%d", &T); while(T--) { m = cnt = 0; scanf("%lld", &n); B = sqrt(n), Primeset(B); for(i=1;i<=n;i=last+1) { w[++m] = n/i; h[m] = w[m]-1; last = n/(n/i); if(n/i<=B) id[n/i] = m; } for(j=1;j<=cnt;j++) { for(i=1;i<=m&&pri[j]*pri[j]<=w[i];i++) { if(w[i]/pri[j]<=B) k = id[w[i]/pri[j]]; else k = n/(w[i]/pri[j]); h[i] = h[i]-(h[k]-(j-1)); } } printf("%lld\n", (F(n, 1)+1)); } return 0; }