The title is the value of the fun (n)
Fun (N) = GCD (3) +GCD (4) +...+GCD (i) +...+GCD (n).
GCD (n) =gcd (c[n][1],c[n][2],......, c[n][n-1])
C[n][k] means the number of the by-choose K things from N things.
N Max 1 million, which is immediately reflected in the possible recursive hit table.
First of all, it must be a push formula, fun (n) is actually a gcd (n) of a first n and, meaningless, directly see GCD (n), put the first few items out, found that the formula is GCD (n) = LCM (1,......, n-1,n)/LCM (1,......, n-1), The LCM is the least common multiple to find several numbers. For example GCD (1) =LCM (1) =1, GCD (2) =LCM (1) = 2,
GCD (6) =LCM (1,2,3,4,5,6)/LCM (1,2,3,4,5) =60/60=1
So I immediately thought of the method, the first screening of the number of 1 million within the prime table, and then from the LCM to recursively push the LCM (1,......, n-1,n), open an array to represent its value (each one of the array represents a prime number, the value of this element factor). However, in this case, the recursion must traverse the prime table, even if only consider a prime number within 1000, also more than 100, it is possible to time out.
But because it is the study of the problem, the spirit of the test, I hit the idea of a dozen, and indeed timed out, it seems that the data is not too much water.
/** Author:ben*/#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<ctime>#include<iostream>#include<algorithm>#include<queue>#include<Set>#include<map>#include<stack>#include<string>#include<vector>#include<deque>#include<list>#include<functional>#include<numeric>#include<cctype>using namespacestd; #ifdef on_local_debug#else#endiftypedefLong LongLL;Const intMAXN =1000009; LL ANS[MAXN];intPN, PT[MAXN], NUM[MAXN];BOOLIP[MAXN];intN =1000000;voidinit_prime_table () {memset (IP,true,sizeof(IP)); inti; ip[1] =false; PN=0; PT[PN++] =2; for(i =4; i < N; i + =2) {Ip[i]=false; } for(i =3; I * I <= N; i + =2) { if(!Ip[i])Continue; PT[PN++] =i; for(ints =2* I, j = i * I; J < N; J + =s) ip[j]=false; } for(; i < N; i++) { if(Ip[i]) {PT[PN++] =i; }}}inlineintMypow (intAintb) {intRET =1; while(b--) {ret*=A; } returnret;}intComput () {ans[1] =1; for(inti =2; I <= N; i++) { if(Ip[i]) {Num[i]++; Ans[i]=i; Continue; } int_GCD =1; intn =i; for(intj =0; J < PN; J + +) { if(n = =1) { Break; } if(N > +&&Ip[n]) { Break; } intt =0; while(n% pt[j] = =0) {T++; N= N/Pt[j]; } if(T >Num[pt[j]]) {_GCD*= Mypow (Pt[j], T-Num[pt[j]]); NUM[PT[J]]=T; }} Ans[i]=_GCD; } for(inti =4; i < MAXN; i++) {Ans[i]+ = Ans[i-1]; } return 0;}intMain () {#ifdef on_local_debug freopen ("data.in","R", stdin);#endif intN;//get_prime_table (MAXN);init_prime_table ();//pn = Pt.size ();memset (NUM,0,sizeof(num)); Comput (); while(SCANF ("%d", &n) = =1) {printf ("%i64d\n", Ans[n]); } return 0;}
Here is the positive solution. The improvement of the method of positive solution is similar to that of the Sieve method to the ordinary method of solving the prime number. The original method works this way: for example, when the recursion to n=8, found that 8 has three factor 2, and the previous LCM only two element factor 2, so this time the value will multiply by another 2. Then the new method directly upside down, when the recursion to 2, found that 2 is a prime number, then the 2^2,2^3,2^4 and so on the ANS in advance by the previous 2. This avoids the traversal of the prime table, reduces complexity, and makes the code more concise. The code is as follows:
/** Author:ben*/#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<ctime>#include<iostream>#include<algorithm>#include<queue>#include<Set>#include<map>#include<stack>#include<string>#include<vector>#include<deque>#include<list>#include<functional>#include<numeric>#include<cctype>using namespacestd; #ifdef on_local_debug#else#endiftypedefLong LongLL;Const intMAXN =1000009; LL ANS[MAXN];intpn, PT[MAXN];BOOLIP[MAXN];intN =MAXN;voidinit_prime_table () {memset (IP,true,sizeof(IP)); inti; ip[1] =false; PN=0; PT[PN++] =2; for(i =4; i < N; i + =2) {Ip[i]=false; } for(i =3; I * I <= N; i + =2) { if(!Ip[i])Continue; PT[PN++] =i; for(ints =2* I, j = i * I; J < N; J + =s) ip[j]=false; } for(; i < N; i++) { if(Ip[i]) {PT[PN++] =i; } }}intComput () {Fill (ans, ans, i +1,1); for(inti =2; I <= N; i++) { if(Ip[i]) {LL T=i; while(T <=N) {ans[t]*=i; T*=i; } } } for(inti =4; i < MAXN; i++) {Ans[i]+ = Ans[i-1]; } return 0;}intMain () {#ifdef on_local_debug//freopen ("test.in", "R", stdin);//freopen ("Data.out", "w", stdout);Freopen ("data.in","R", stdin);#endif intN; Init_prime_table (); Comput (); while(SCANF ("%d", &n) = =1) {printf ("%i64d\n", Ans[n]); } return 0;}
bjfu1211 push formula, sieve prime