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

题目链接: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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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 P;
const int Inf = 0x3f3f3f3f;
const double eps = 1e-8;
const int mod=998244353;
const int maxn = 2e6+5;
template  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<

 

你可能感兴趣的:(差分数组,思维)