ACM-ICPC 2018 南京赛区网络预赛 J-Sum(推公式)

ACM-ICPC 2018 南京赛区网络预赛 J-Sum

链接
ACM-ICPC 2018 南京赛区网络预赛 J-Sum(推公式)_第1张图片题意:f(i)表示a*b的对数(a,b都不含平方因子)。 求
∑ i = 1 n f i \sum_{i=1}^{n} f_i i=1nfi
思路:
∑ i = 1 n f i = ∑ i = 1 n ∑ d ∣ i ∣ u ( d ) ∣ ∣ u ( i d ) ∣ = ∑ i = 1 n ∣ u ( i ) ∣ ∑ j = 1 ⌊ n i ⌋ ∣ u ( j ) ∣ \sum_{i=1}^{n} f_i = \sum_{i=1}^{n} \sum_{d|i}^{} |u(d)||u(\frac{i}{d})|=\sum_{i=1}^{n} |u(i)| \sum_{j=1}^{\lfloor\frac{n}{i}\rfloor} |u(j)| i=1nfi=i=1ndiu(d)u(di)=i=1nu(i)j=1inu(j)
先莫比乌斯函数前缀和瞎搞一下,然后再整除分块,就完事了?

#include
#define ll long long
using namespace std;
const int maxn = 2e7 + 10;
const ll mod = 1e9 + 7;
ll n,m;

bool v[maxn];
int cnt;
ll p[maxn],mob[maxn];

void getmob(){
	memset(v,0,sizeof(v));
	memset(p,0,sizeof(p));
	memset(mob,0,sizeof(mob));
	cnt = 0;
	mob[1] = v[1] = 1;
	for(int i = 2;i < maxn;i++){
		if(!v[i]){
			p[++cnt] = i;
			mob[i] = -1;
		}
		for(int j = 1;j <= cnt && i * p[j] <= maxn;j++){
			v[i * p[j]] = 1;
			if(i % p[j] == 0){
				mob[i * p[j]] = 0;
				break;
			}
			else {
				mob[i * p[j]] = -mob[i];
			}
		}
	}
	for(int i = 1;i < maxn;i++){
		if(mob[i] < 0)mob[i] = -mob[i];
	}
	for(int i = 1;i < maxn;i++){
		mob[i] = mob[i] + mob[i - 1];
	}
	return ;
}

ll calc1(ll n){
	ll res = 0;
	for(ll l = 1,r;l <= n;l = r + 1){
		r = n / (n / l);
		res += (mob[r] - mob[l - 1]) * mob[n / l];
	}
	return res;
}

int main() {
//    ios::sync_with_stdio(false);
//    cin.tie(0);
	getmob();
	int t;
	scanf("%d",&t);
	for(int ca = 1; ca <= t; ca++) {
		scanf("%lld",&n);
		ll ans = calc1(n);
		printf("%lld\n",ans);
	}
	return 0;
}

//Dawn_Exile




你可能感兴趣的:(ACM,icpc)