列表

详情


NC232182. 依古比古是OP

描述

依古比古 喜欢原神。

为了更好的管理角色,依古比古 给每个角色赋了一个权值,构成一个权值序列 

不幸的是,依古比古 的记性并不好,他甚至忘记了序列  具体长啥样,只记得序列  是一个长度为  的严格单调递增的正整数序列,且满足 

同时,为了方便管理,依古比古 实现了一个奇怪的算法:

image-20211215175631901

容易看出,这个算法的作用是找到序列  中第一个大于  的位置。

现在,依古比古 给出了  次询问 ,他想要知道在所有可能的序列  上运行 Search(x[i]) 调用 Check 函数的次数的和。

由于答案和输出量很大,令第  次询问的答案为 ,你只需要输出( 表示异或): ,即 的异或和。


输入描述

输入第一行三个整数  (  ) ,分别表示序列长度、序列中元素的范围和询问次数。

第二行  个整数  (  ),表示询问。

输出描述

  输出一行一个整数表示压缩后的答案。

示例1

输入:

3 4 5
0 1 2 3 4

输出:

20

说明:

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 307ms, 内存消耗: 19984K, 提交时间: 2022-03-12 14:51:21

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define maxn 2000000
using namespace std;
int n,m,q,x;
int fac[2000005],ifac[2000005],ans[1000005];
ll Ans;

ll read(){
    ll x=0,w=0;char ch=getchar();
    while(!isdigit(ch)) w|=(ch=='-'),ch=getchar();
    while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return w?-x:x;
}

void print(ll x){
	if(x>=10) print(x/10);
	putchar(x%10+'0');
}

int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1) res=1ll*res*x%mod;
		x=1ll*x*x%mod,y/=2;
	}
	return res;
}

int C(int x,int y){
	if(x<y) return 0;
	int res=1ll*fac[x]*ifac[y]%mod*ifac[x-y]%mod;
	return res;
}

int main(){
	n=read(),m=read(),q=read();
	fac[0]=1;
	for(int i=1;i<=maxn;i++) fac[i]=1ll*i*fac[i-1]%mod;
	ifac[maxn]=ksm(fac[maxn],mod-2);
	for(int i=maxn-1;i>=0;i--) ifac[i]=1ll*(i+1)*ifac[i+1]%mod;
	for(int i=0;i<=m;i++) ans[i]=2ll*C(m,n)%mod;
	int pos=0;
	for(int l=1;;l*=2){
		if(pos+l<=n){
			pos+=l;
			int add=0;
			for(int i=0;i<=m;i++){
				(add+=2ll*C(i-1,pos-1)*C(m-i,n-pos)%mod)%=mod;
				(ans[i]+=add)%=mod;
			}
		}
		else break;
	}
	for(int i=1;i<=q;i++){
		x=read();
		Ans^=1ll*i*ans[x];
	}
	print(Ans),puts("");

	return 0;
}

上一题