A“一个部族,一个民族,一个弗雷尔卓德。”(素数筛,逆序对,树状数组)

“一个部族,一个民族,一个弗雷尔卓德。”
Description

寒冰射手艾希新学会了一个技能,艾希通过这个技能成为了一名声名远扬的神箭手,从此再也无人敢侵犯弗雷尔卓德!

这个技能的描述如下(假设英雄联盟内的每个人都有一个编号):

假设艾希有x-1(x>=2)x−1(x>=2)个敌人,每个敌人的编号分别为1;;1~;;x-1x−1,那么艾希的编号就是xx。艾希每次使用这个技能,那么对于某个敌人,如果这个敌人的编号的最小素因子小于等于艾希的编号的最小素因子,那么艾希能对他造成致命一击。

现在假设已知有tt场战争,每场战争有x-1x−1个敌人,艾希想知道她每场战争使用这个技能能对多少个敌人造成致命一击,由于这个数目太大,她无法计算所以希望你编写一个程序来帮她计算这个结果。

一个数xx的最小素因子:能够整除xx的最小素数。比如2和4的最小素因子是2,3的最小素因子是3。我们知道1不是素数,但是为了题目的完整性,在这里我们定义1的最小素因子为1。

Input

一个正整数t(t<=1000000)t(t<=1000000),表示有t组数据。

每组数据输入一个整数x(2<=x<=1000000)x(2<=x<=1000000),表示艾希的编号为xx,且敌人数量为x-1x−1。

Output

对于每组数据输出一个整数ans,表示艾希在这场战争中使用该技能能对ans个敌人造成致命一击。

Sample Input 1

2
2
6
Sample Output 1

1
3
Hint

对于6这个数据,我们知道1~6的每个数的最小素因子依次为1、2、3、2、5、2,因此编号为1、2、4的敌人将会受到致命一击。

Source

2019年集训队选拔赛

#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

#define ll long long
const ll maxn = 1000000 + 10;

ll T;
ll n;
ll c[maxn];
ll sum[maxn];
bool is_prime[maxn];
ll yinzi[maxn];
ll cnt;
ll ans[maxn];

void Add(ll x,ll y)
{
	for ( ; x <= maxn && x; x += x & -x )
		c[x] += y;
}
int Summ(ll x)
{
	int ans = 0;
	for ( ; x; x -= x & -x )
		ans += c[x];
	return ans;
}

void init()
{
	memset(c,0,sizeof(c));
	memset(yinzi,0,sizeof(yinzi));
	yinzi[1] = 1;
	for(int i = 2;i<=maxn;i++)
	{
		for(int j = i;j<=maxn;j += i)
		{
			if(!yinzi[j])
				yinzi[j] = i;
		}
	}
	for(int i = 1;i<=maxn;i++)
	{
		ans[i] = Summ(yinzi[i]); 
		Add(yinzi[i],1);
	}
	
}

int main()
{
	init();
	scanf("%lld",&T);
	while(T--)
	{
		ll n;
		scanf("%lld",&n);
		printf("%lld
",ans[n]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/tomjobs/p/10612574.html