2021.3.26 正睿憨批赛
2021.3.26 正睿憨批赛
为什么称之为憨批赛呢?因为在这场比赛中,我发现了自己憨逼的本质
"一个对着错误类欧敲了一个上午的人如果还不是憨批,那么只有不仅敲了一个上午假类欧,还在最后改成皮克定理的人才是憨批" ——沃兹基·硕德
T1
题意:定义函数\(f_k:a\rightarrow b\),其中\(\forall i\in[0,n-1],b_i={\Large\oplus}_{j=0}^{k-1}a_{(i+k)\%n}\)
令\(f_{k,0}(x)=f_k(x),f_{k,i}(x)=f_k(f_{k,i-1}(x))\)
求\(f_{k,T}(a)\).
\(|a|=n\leq 5\times 10^5,T\leq 10^{18},a_i\leq 10^9\)
不难发现异或卷积等价于值域对位模2意义下卷积(下文均为模2意义下)
转换为\(a*(1+x+x^2+\cdots+x^{k-1})^T \equiv b \pmod {x^n-1}\)
不难想到\(O(n\log_2^2n)\)的\(\tt NTT+quickpow\)
但是显然会\(\rm TLE\)
考虑特殊性质
不难证明\((1+x+x^2+\cdots+x^{k-1})^{2^\omega}\equiv 1+x^{2^\omega}+x^{2\cdot2^\omega}+\cdots+x^{(k-1)2^\omega}\pmod {x^n-1}\)
证明:令\(g(x)=\sum_{i=0}^{k-1}x^i\),求证命题\(g(x)^{2^\omega}=g(x^{2^\omega})\)
当\(\omega=1\)时
\[g(x)^2=(1+x^2+x^4+\cdots+x^{2(k-1)})+2\sum_{i,j\in[0,k-1],i\not =j}x^ix^j\\ =1+x^2+x^4+\cdots+x^{2(k-1)}\\ =g(x^2) \]当\(\omega > 1\)时,当\(x< \omega\)时成立
\[g(x)^{2^\omega}=(g(x)^{2^{\omega-1}})^2\\ =g(x^{2^{\omega-1}})^2\\ =g(x^{2^\omega}) \]\(\rm Q.E.D\)
所以我们先对\(T\)二进制分解,每次对分解出的\(\lambda\)提取出置换(下式模\(n\))\(\left(\begin{matrix}0&1&2&\cdots& n-1\\2^\lambda&1+2^\lambda&2+2^\lambda&\cdots&n-1+2^\lambda\end{matrix}\right)\)
的每个循环单独进行转移
时间复杂度为\(O(n\log_2T)\)
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define read read1<ll>()
# define Type template<typename T>
Type T read1(){
T t=0;char k;bool vis=0;
do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
int a[500005],b[500005];
bool vis[500005];
vector<int>tem;
int main(){
int s=read,m=read;ll T=read;
for(int i=0;i<s;++i)a[i]=read;
for(ll k=1;T;k<<=1)
if(T&k){
T^=k;int x=k%s;
memset(vis,0,s);
memcpy(b,a,s<<2);
for(int i=0;i<s;++i)
if(!vis[i]){tem.clear();
int ans=0,S=0,r=0;
for(int j=i;!vis[j];j=(j+x)%s)
tem.push_back(j),S^=b[j],vis[j]=1;
if((m/tem.size())&1)ans=S;
r=m%tem.size();
for(int j=0;j!=r;j=(j+1)%tem.size())
ans^=b[tem[j]];
for(int j=0;j<tem.size();++j){
a[tem[j]]=ans;
ans^=b[tem[j]];
ans^=b[tem[(j+m)%tem.size()]];
}
}
}
for(int i=0;i<s;++i)printf("%d ",a[i]);
return 0;
}
T2
求\(\sum_{i=0}^n\sum_{j=0}^\infty [j\leq i\sqrt{p\over q}]\),共\(T\)组
\(T\in[1,10^5].p,q\in[1,1000],n\in[1,10^9]\)
如果没有根号,那就是一个简单的类欧
可是有根号
所以我们考虑使用一个有理数\(\xi\)去拟合这个无理数\(\psi\)(也可能是有理数)
首先需要满足\(\forall x\in [1,n],\lfloor i\psi\rfloor =\lfloor i\xi\rfloor\)
其次分子与分母不能太大,不能超过\(\tt longlong\)(其实也可以超过,如果你不嫌难打,也不怕\(\rm T\))
所以我们考虑在\(\tt Stern-Brocot-Tree\)上进行逼近
其实可以树上倍增加判定,时间复杂度为\(O(\log_2q\log_2\log_2q)\)
其实暴力跳也是可以的,如果特判掉\(\frac{p}{q}=\xi^2\)的情况,因为一般情况下期望时间复杂度为\(\log_2q\),但是有理数会被卡
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define read read1<ll>()
# define Type template<typename T>
Type T read1(){
T t=0;char k;bool vis=0;
do (k=getchar())=='-'&&(vis=1);while('0'>k||k>'9');
while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
int cnt;
void pr(__int128 x){
if(x<10)putchar(x+'0');
else pr(x/10),putchar(x%10+'0');
}
pair<ll,ll> query(pair<ll,ll>W,pair<ll,ll>x,pair<ll,ll>y,pair<ll,ll>z){
if(y.second>=1e17||y.first>=1e17)return x;
if((__int128)W.first*y.second*y.second<(__int128)W.second*y.first*y.first)
return query(W,x,make_pair(x.first+y.first,x.second+y.second),y);
return query(W,y,make_pair(y.first+z.first,y.second+z.second),z);
}
__int128 query(ll p,ll q,ll b,ll n){
if(!p)return 0;//cout<<p<<' '<<q<<' '<<n<<endl;
if(p>=q||b>=q)return (__int128)p/q*n*(n+1)/2+(__int128)b/q*(n+1)+query(p%q,q,b%q,n);
__int128 m=(__int128)p*n+b;m/=q;
return m*n-query(q,p,q-b-1,m-1);
}
int main(){//fre("ex_B3");
for(int T=read;T--;){
ll p=read,q=read,n=read;
ll v=__gcd(p,q);p/=v;q/=v;
pair<ll,ll>t;
if((ll)sqrt(p)*(ll)sqrt(p)==p&&(ll)sqrt(q)*(ll)sqrt(q)==q)t=make_pair(sqrt(p),sqrt(q));
else t=query(make_pair(p,q),make_pair(0,1),make_pair(1,1),make_pair(1,0));
pr(query(t.first,t.second,0,n)+n+1);putchar('\n');
cnt=0;
}
return 0;
}
浮世苍茫,不过瞬逝幻梦
善恶爱诳,皆有定数
于命运之轮中
吞噬于黄泉之冥暗
呜呼,吾乃梦之戍人
幻恋之观者
唯于万华镜中,永世长存