zoukankan      html  css  js  c++  java
  • UOJ188 Sanrd Min_25筛

    传送门


    省选之前做数论题会不会有Debuff啊

    这道题显然是要求(1)(x)中所有数第二大质因子的大小之和,如果不存在第二大质因子就是(0)

    线性筛似乎可以做,但是(10^{11})的数据范围让人望而却步,而杜教筛需要对(f(x))找到一个函数(g(x))做狄利克雷卷积成为一个好算前缀和的函数(h(x))相信各位是找不到这样一个函数的。所以考虑Min_25筛。但用Min_25筛还不知道要筛什么东西,故从Min_25筛最后的计算过程入手。

    Min_25筛的每一层递归中计算了两种数对答案的贡献:①当前被拼出的数乘上一个质数的若干次方产生的数的贡献;②当前被拼出的数乘上一个质数的若干次方再乘上其他质数产生的数的贡献。对于②的贡献我们递归处理,所以只需考虑①的情况。

    ①中,如果乘上的质数的指数(> 1),产生贡献的就是当前质因子,否则就是上一个被乘上的因子。上一个被乘上的因子在递归过程中已经传递了,所以我们只需要上一个被乘上的因子产生了多少次贡献,即在一段区间内共有多少个质数。所以筛出(forall x in [1,N] sumlimits_{i=1}^{frac{N}{x}} [i in Prime])就可以计算答案。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define int long long
    inline int read(){
    	int a = 0;
    	char c = getchar();
    	while(!isdigit(c)) c = getchar();
    	while(isdigit(c)){
    		a = a * 10 + c - 48;
    		c = getchar();
    	}
    	return a;
    }
    
    const int MAXN = 1e6 + 7;
    int prm[MAXN] , cnt;
    bool nprm[MAXN];
    
    void init_prm(){
    	for(int i = 2 ; i <= 1e6 ; ++i){
    		if(!nprm[i])
    			prm[++cnt] = i;
    		for(int j = 1 ; i * prm[j] <= 1e6 ; ++j){
    			nprm[i * prm[j]] = 1;
    			if(i % prm[j] == 0) break;
    		}
    	}
    }
    
    int id1[MAXN] , id2[MAXN] , val[MAXN << 1] , f[MAXN << 1] , N , T , Cnt;
    
    int find(int x){return x <= T ? id1[x] : id2[N / x];}
    
    void init_Min25(){
    	T = sqrt(N); Cnt = 0;
    	for(int i = 1 , pi ; i <= N ; i = pi + 1){
    		int cur = N / i;
    		pi = N / cur;
    		val[cur <= T ? id1[cur] = ++Cnt : id2[pi] = ++Cnt] = cur;
    		f[Cnt] = cur - 1;
    	}
    	for(int i = 1 ; i <= cnt && prm[i] * prm[i] <= N ; ++i){
    		int p = find(prm[i - 1]);
    		for(int j = 1 ; val[j] >= prm[i] * prm[i] ; ++j){
    			int q = find(val[j] / prm[i]);
    			f[j] -= f[q] - f[p];
    		}
    	}
    }
    
    int solve(int x , int p){
    	if(prm[p] > x) return 0;
    	int sum = (f[find(x)] - f[find(prm[p - 1])]) * prm[p - 1];
    	for(int j = p ; j <= cnt && prm[j] * prm[j] <= x ; ++j){
    		int times = prm[j];
    		while(times * prm[j] <= x){
    			sum += solve(x / times , j + 1) + prm[j];
    			times *= prm[j];
    		}
    	}
    	return sum;
    }
    
    int work(){init_Min25(); return solve(N , 1);}
    
    signed main(){
    	init_prm();
    	cin >> N; --N; int sum = work();
    	cin >> N; cout << work() - sum;
    	return 0;
    }
    
    
  • 相关阅读:
    Pytorch1.0入门实战二:LeNet、AleNet、VGG、GoogLeNet、ResNet模型详解
    Pytorch1.0入门实战一:LeNet神经网络实现 MNIST手写数字识别
    浅谈RNN、LSTM + Kreas实现及应用
    tensorflow 1.12.0 gpu + python3.6.8 + win10 + GTX1060 + cuda9.0 + cudnn7.4 + vs2017)
    高手详解SQL性能优化十条经验
    SQL语句操作符优化
    SQL优化
    34条简单的SQL优化准则
    销售订单无法使用折扣(其他可以正常使用)
    EBS FORM FOLDER 开发,单元格无法使用右键
  • 原文地址:https://www.cnblogs.com/Itst/p/10660039.html
Copyright © 2011-2022 走看看