• BZOJ3944 Sum


    @(BZOJ)[杜教筛]

    Description

    Description

    Input

    一共T+1行
    第1行为数据组数T(T<=10)
    第2~T+1行每行一个非负整数N,代表一组询问

    Output

    一共T行,每行两个用空格分隔的数ans1,ans2

    Sample Input

    6
    1
    2
    8
    13
    30
    2333
    

    Sample Output

    1 1
    2 0
    22 -2
    58 -3
    278 -3
    1655470 2
    

    Solution

    入门模板题.
    注意一点点常数优化的技巧: 调用函数时传入参数的速度是很慢的, 要尽量控制传入参数的数量和参数的类型大小.

    #include <cstdio>
    #include <cstring>
    
    const long long BND = 4000000;
    int n;
    long long sum1[BND], sum2[BND], vis[600], _sum[600];
    
    inline void pretreat()
    {
    	static int vis[BND], prm[BND], phi[BND], mu[BND];
    	memset(phi, 0, sizeof(phi));
    	int cnt = 0;
    	mu[1] = phi[1] = 1;
    
    	for(int i = 2; i < BND; ++ i)
    	{
    		if(! phi[i])
    			prm[cnt ++] = i, mu[i] = -1, phi[i] = i - 1;
    
    		for(int j = 0; j < cnt && i * prm[j] < BND; ++ j)
    		{
    			int crt = i * prm[j];
    
    			if(! (i % prm[j]))
    			{
    				mu[crt] = 0;
    				phi[crt] = phi[i] * prm[j]; // phi[k * prm[j] ^ (k + 1)] / phi[k * prm[j] ^ k] = prm[j]
    				break;
    			}
    
    			mu[crt] = - mu[i];
    			phi[crt] = phi[prm[j]] * phi[i];
    		}
    	}
    	
    	sum1[0] = sum2[0] = 0;
    
    	for(int i = 1; i < BND; ++ i)
    		sum1[i] = sum1[i - 1] + phi[i], sum2[i] = sum2[i - 1] + mu[i];
    }
    
    long long getPhiSum(int crt)
    {
    	if(crt < BND)
    		return sum1[crt];
    
    	int tmp = n / crt;
    
    	if(vis[tmp])
    		return _sum[tmp];
    
    	_sum[tmp] = crt * ((long long)crt + 1) / 2;
    
    	for(int i = 2, lst; i <= crt; i = lst + 1) {
    		lst = crt / (crt / i), _sum[tmp] -= getPhiSum(crt / i) * (lst - i + 1);
    		if (lst==n) break;
    	}
    
    	vis[tmp] = 1;
    	return _sum[tmp];
    }
    
    long long getMuSum(int crt)
    {
    	if(crt < BND)
    		return sum2[crt];
    
    	int tmp = n / crt;
    
    	if(vis[tmp])
    		return _sum[tmp];
    
    	_sum[tmp] = 1;
    
    	for(int i = 2, lst; i <= crt; i = lst + 1) {
    		lst = crt / (crt / i), _sum[tmp] -= getMuSum(crt / i) * (lst - i + 1);
    		if (lst==n) break;
    	}
    	
    	vis[tmp] = 1;
    	return _sum[tmp];
    }
    
    int main()   
    {
    	#ifndef ONLINE_JUDGE
    	freopen("BZOJ3944.in", "r", stdin);
    	freopen("BZOJ3944.out", "w", stdout);
    	#endif
    	
    	pretreat();
    	int T;
    
    	for(scanf("%d", &T); T --;)
    	{   
    		scanf("%d", &n);
    		memset(vis, 0, sizeof(vis));
    		long long ans1 = getPhiSum(n);
    		memset(vis, 0, sizeof(vis));
    		long long ans2 = getMuSum(n);
    		printf("%lld %lld
    ", ans1, ans2);
    	}
    } 
    
  • 相关阅读:
    ASP.NET程序中常用的三十三种代码
    uri
    用XML保存和读取图片
    location
    访问相关节点
    onkeyup,onkeydown,onkeypress
    Asp.net中Server.Transfer,Server.Execute和Response.Redirect的区别
    关于window.showModalDialog()返回值的学习心得
    WP7数据绑定
    hdu 1568
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6701223.html
Copyright © 2020-2023  润新知