zoukankan      html  css  js  c++  java
  • BZOJ 3944: Sum (杜教筛)

    惊险…卡着时限过了…

    注意有的地方可能爆int(因为有23112^{31}-1)

    有几个地方可能会蜜汁RE,具体看代码注释

    CODE

    9000ms卡过2333

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int MAXN = 1000005;
    int prime[MAXN/10], cnt;
    LL mu[MAXN], phi[MAXN];
    bool vis[MAXN];
    inline void Pre_Work(int n) {
    	mu[1] = phi[1] = 1;
    	for(int i = 2; i <= n; ++i) {
    		if(!vis[i])
    			prime[++cnt] = i, mu[i] = -1, phi[i] = i-1;
    		for(int j = 1; j <= cnt && i*prime[j] <= n; ++j) {
    			vis[i*prime[j]] = 1;
    			if(i % prime[j] == 0) {
    				mu[i*prime[j]] = 0;
    				phi[i*prime[j]] = phi[i] * prime[j];
    				break;
    			}
    			mu[i*prime[j]] = -mu[i];
    			phi[i*prime[j]] = phi[i] * (prime[j]-1);
    		}
    	}
    	for(int i = 2; i <= n; ++i)
    		mu[i] += mu[i-1], phi[i] += phi[i-1];
    }
    map<int, int>MU;
    int sum_mu(int n) {
    	if(n < MAXN) return mu[n];
    	if(MU.count(n)) return MU[n];
    	int re = 1;
    	for(int i = 2, j; i > 0 && i <= n; i = j+1) { //这里i=j+1会爆int
    		j = n/(n/i);
    		re -= (j-i+1) * sum_mu(n/i);
    	}
    	return MU[n]=re;
    }
    map<int, LL>PHI;
    LL sum_phi(int n) {
    	if(n < MAXN) return phi[n];
    	if(PHI.count(n)) return PHI[n];
    	LL re = 1ll * n * (1ll*n+1) / 2; //这里+1也会爆int
    	for(int i = 2, j; i > 0 && i <= n; i = j+1) { //这里i=j+1会爆int
    		j = n/(n/i);
    		re -= sum_phi(n/i) * (j-i+1);
    	}
    	return PHI[n]=re;
    }
    int main() {
    	int n, T;
    	scanf("%d", &T);
    	Pre_Work(MAXN-1);
    	while(T--) {
    		scanf("%d", &n);
    		printf("%lld %d
    ", sum_phi(n), sum_mu(n));
    	}
    }
    
  • 相关阅读:
    移位运算符的限制
    数据类型
    正无穷和负无穷的问题
    dos下的cd指令
    c#线程的几种启动方法
    储过程实现简单的数据分页
    java 身份证15位转18位
    eclipse配置文件内存设置
    markdown语法学习
    js工具类
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039292.html
Copyright © 2011-2022 走看看