NC232182. 依古比古是OP
描述
依古比古 喜欢原神。
为了更好的管理角色,依古比古 给每个角色赋了一个权值,构成一个权值序列 。
不幸的是,依古比古 的记性并不好,他甚至忘记了序列 具体长啥样,只记得序列 是一个长度为 的严格单调递增的正整数序列,且满足 。
同时,为了方便管理,依古比古 实现了一个奇怪的算法:
容易看出,这个算法的作用是找到序列 中第一个大于 的位置。
现在,依古比古 给出了 次询问 ,他想要知道在所有可能的序列 上运行 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; }