G
思路
因此有。因为,结合式子可以发现,即。所以考虑枚举余数。当确定时,与是一一对应的(原式形如一次函数)。因此只要确定有多少个满足条件,就可以知道当前的对答案的贡献是多少。
首先根据已知,。又因为,且,得到。综上:。其中每个都可以贡献一次答案。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(ll (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
void solve()
{
ll x,y;
In(2,&x,&y);
ll lim=sqrt(x);
ll ans=0;
rep(k,1,lim)
{
ans+=max(0ll,min(y,(x-k)/k)-k);
}
Out(1,ans);
}
int main()
{
int _;
cin>>_;
while(_--)
{
solve();
}
}
J
思路
异或运算满足结合律,因此可以维护一个异或和来找MEX。考虑如何快速地找MEX,这里用到了,将所有的数字加入中,并维护每个结点的子树大小。对于一次查询,从根节点向下贪心,途中维护答案。如果异或和的下一位为,选的叶结点更优,如果的子树已经满了,就只能选。如果异或和的下一位为,就反过来做。另外要注意如果有一个要选的子树为空,直接输出当前结果即可。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int (i)=(st);(i)<=(ed);++(i))
#define bl(u,i) for(int (i)=head[(u)];(i);(i)=e[(i)].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=6E6+10;
ll n,m,tot=1;
ll a[N],t[N][2],siz[N];
void insert(ll val)
{
ll cur=1;
for(int i=19;i>=0;--i)
{
++siz[cur];
if(val&(1<<i))
{
if(!t[cur][1])
t[cur][1]=++tot;
cur=t[cur][1];
}
else
{
if(!t[cur][0])
t[cur][0]=++tot;
cur=t[cur][0];
}
}
++siz[cur];
}
ll query(ll val)
{
ll cur=1,ret=0;
for(int i=19;i>=0;--i)
{
if(val&(1<<i))
{
if(!t[cur][1])
return ret;
if(siz[t[cur][1]]==1<<i)
{
cur=t[cur][0];
ret+=1<<i;
}
else
cur=t[cur][1];
}
else
{
if(!t[cur][0])
return ret;
if(siz[t[cur][0]]==1<<i)
{
cur=t[cur][1];
ret+=1<<i;
}
else
cur=t[cur][0];
}
}
return ret;
}
int main()
{
In(2,&n,&m);
rep(i,1,n)
In(1,&a[i]);
sort(a+1,a+n+1);
n=unique(a+1,a+n+1)-a-1;
rep(i,1,n)
insert(a[i]);
ll sum=0,x;
while(m--)
{
In(1,&x);
sum^=x;
Out(1,query(sum));
}
}