题意:
定义F(n)=∑i=1n∑j=1n[gcd(i,j)+lcm(i,j)⩾n]F(n)=∑i=1n∑j=1n[gcd(i,j)+lcm(i,j)⩾n],其中[][]是艾弗森约定,现在要求出ansn=∑i=1nF(i)ansn=∑i=1nF(i).
思路:
如果定义T(n)=∑i=1n∑j=1n[gcd(i,j)+lcm(i,j)=n]T(n)=∑i=1n∑j=1n[gcd(i,j)+lcm(i,j)=n],那么Fn=i∗i−∑i=1n−1T(i)Fn=i∗i−∑i=1n−1T(i),因为不可能存在i⩾ni⩾n或者j⩾nj⩾n时有gcd(i,j)+lcm(i,j)=ngcd(i,j)+lcm(i,j)=n,看T(n)T(n)怎么算:
T(n)=∑d=1n∑i=1⌊nd⌋∑j=1⌊nd⌋[gcd(i,j)=1][i∗j∗d+d=n]T(n)=∑d=1n∑i=1⌊nd⌋∑j=1⌊nd⌋[gcd(i,j)=1][i∗j∗d+d=n]
=∑d=1n∑i=1⌊nd⌋∑j=1⌊nd⌋[gcd(i,j)=1][(i∗j+1)d=n]=∑d=1n∑i=1⌊nd⌋∑j=1⌊nd⌋[gcd(i,j)=1][(i∗j+1)d=n]
=∑d|n∑i=1nd∑j=1nd[gcd(i,j)=1][(i∗j+1)d=n]=∑d|n∑i=1nd∑j=1nd[gcd(i,j)=1][(i∗j+1)d=n]
=∑d|n∑i=1nd∑j=1nd[gcd(i,j)=1][i∗j=nd−1]=∑d|n∑i=1nd∑j=1nd[gcd(i,j)=1][i∗j=nd−1]
=∑d|n∑i=1nd∑j=1nd[gcd(i,j)=1][j=nd−1i]=∑d|n∑i=1nd∑j=1nd[gcd(i,j)=1][j=nd−1i]
=∑d|n∑i=1nd[gcd(i,nd−1i)=1]=∑d|n∑i=1nd[gcd(i,nd−1i)=1]
=∑d|n∑i=1nd−1[gcd(i,nd−1i)=1]=∑d|n∑i=1nd−1[gcd(i,nd−1i)=1]
记f(x)=∑i|x[gcd(i,xi)=1]f(x)=∑i|x[gcd(i,xi)=1],如果ii和互素,那么可以知道ii要么完全拥有的素因子,要么完全没有xx的素因子,暴力搜索一下素因子产生的因子即可,不用gcdgcd去判断,因为那样时间就变成O(nlg2n).....O(nlg2n).....,会超时的。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 1e6 + 5;
const ll mod = 258280327;
using namespace std;
typedef pair<int, int> pa;
int a[maxn];
pa pri[1000]; int num;
void div(int x) {
while(x > 1) {
int now = a[x];
if(!num || pri[num - 1].first != now) pri[num++] = pa(now, 1);
else pri[num - 1].second++;
x /= now;
}
}
int vec[1000], cnt, T;
void dfs(ll &ans, int sol, int sum, int id, int flag) {
if(id == num) {
int y = sol / sum;
vec[cnt++] = sum;
if(!flag) ans++;
return ;
}
int k = 1, g = flag;
for(int i = 0; i <= pri[id].second; i++) {
if(!i || i == pri[id].second) flag = 0;
else flag = 1;
dfs(ans, sol, sum * k, id + 1, g | flag);
k *= pri[id].first;
}
}
ll ans[maxn], rec[maxn];
ll seq[maxn], f[maxn], tot[maxn];
void solve() {
int max_p = 0;
for(ll i = 1; i <= 1000000; i++) {
num = 0; div(i); cnt = 0;
dfs(f[i], i, 1, 0, 0);
rec[i] = i * i;
rec[i] = rec[i] - tot[i - 1];
for(int j = 0; j < cnt; j++) {
int x = vec[j];
seq[i] += f[x - 1];
}
tot[i] = tot[i - 1] + seq[i];
ans[i] = ans[i - 1] + rec[i];
}
}
int main() {
for(ll i = 2; i < maxn; i++) {
if(a[i]) continue;
a[i] = (int) i;
for(ll j = i * i; j < maxn; j += i) if(!a[j]) a[j] = i;
}
solve(); int n;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
printf("%lld\n", ans[n] % mod);
}
return 0;
}