牛客-算式子(思维+差分)

题目链接:https://ac.nowcoder.com/acm/contest/6290/E

这个题目要将求得的m个结果进行异或后输出结果。

对于每一个结果x的值是一定的,但有n个ai值,求

1.对于前半部分,因为x的值一定,只需统计 [k*x,(k+1)*x) 的ai的数即可。

2.对于后半部分较为麻烦,显然对于每个x,只需计算比x小的ai。遍历每一个值,利用差分数组来进行统计。

对于任意一个值a来说,在[a,2*a)区间的数,结果为1,ans[a]++,在[2*a,3*a)区间的数结果为2,ans[2*a]++,以此类推。

最后差分数组求和即可获得答案。具体看代码。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#define cla(a, sum) memset(a, sum, sizeof(a))
#define rap(i, m, n) for(int i=m; i<=n; i++)
#define rep(i, m, n) for(int i=m; i>=n; i--)
#define bug printf("???\n")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
const int Inf = 0x3f3f3f3f;
const double eps = 1e-8;
const int mod=998244353;
const int maxn = 2e6+5;
template <typename T> void read(T &x){
    x = 0; int f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
}

int n,m; 
ll cnt[maxn]={0},num[maxn]={0};
ll ans1[maxn]={0},ans2[maxn]={0};

int main()
{
	//ios::sync_with_stdio(false);
	read(n);read(m);
	rap(i,1,n){
		int c;read(c);
		cnt[c]++;num[c]++;//记录个数 
	}
	rap(i,1,m)cnt[i]+=cnt[i-1];
	rap(i,1,m){
		int j;
		for(j=2*i;j<=m;j+=i){//[k*i,(k+1)*i)中的ai的个数*k 
			ans1[i]+=(cnt[j-1]-cnt[j-i-1])*((j-i)/i);
		}
		ans1[i]+=(cnt[m]-cnt[j-i-1])*((j-i)/i);//注意ai<=m,要特殊处理 
	} 
	rap(i,1,m){//利用差分数组 
		ans2[i]+=num[i];
		for(int j=2*i;j<=m;j+=i){
			ans2[j]+=num[i];
		}
	}
	ll ans=0;
	rap(i,1,m){
		ans2[i]+=ans2[i-1];//差分数组不断求和 
		ans1[i]+=ans2[i];//两者加和 
		ans=ans^ans1[i];
	}
	cout<<ans;

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值