Luogu7738
引言
同步赛,大常数选手卡常题过了!感动!
看到这题——az,什么字符串神仙题?01-Trie 上自动机?
看到 gen.cpp
,笑了,字典是随机的,因此我们可以考虑乱搞。
说句闲话,有没有人强制离线过的?很好奇。
思路
注意到 \(k\le15\),因此我们如果把长为 \(256\) 的串均分 \(16\) 块,每块长为 \(16\),那么噪音干扰位(不匹配位)最多只会在其中 \(15\) 块中,因此必然会有一块是全匹配的。
对每一块,我们考虑,其状态不会超过 \(65536\) 种,而字典大致随机均分其中,每种情况有 \(\dfrac{400000}{65536}\approx6\) 的单词满足。
于是把字典中的每种情况插进一个 vector
表中,每次暴力查表,查到即有解,否则无解。
判断时可能要 bitset
的异或与 count
等,建议手写一个,避免卡常。
复杂度分析
时空分析
为了更直观,我们把常数写进时间复杂度记号中。
预处理(包括 count
预处理)约 \(O(256n+16n+65536)\)。
单次询问约 \(O(16\times6\times\frac{256}{w})\),手写的话 \(w\) 约 \(64\)?
因为又要异或又要 count
,可能还有一个 \(2\) 的常数得乘上。
空间的话稍微证一下是会发现不会爆的。
代码难度分析
还好吧(?),反正是我同步赛唯一做出的题(到时候被不被少爷机卡常就不知道了)。
上代码。
#include <stdio.h>
#include <vector>
typedef long long llt;
typedef unsigned short usint;
typedef unsigned uint;typedef unsigned long long ullt;
typedef bool bol;typedef char chr;typedef void voi;
typedef double dbl;
template<typename T>bol _max(T&a,T b){return(a<b)?a=b,true:false;}
template<typename T>bol _min(T&a,T b){return(b<a)?a=b,true:false;}
template<typename T>T power(T base,T index,T mod){return((index<=1)?(index?base:1):(power(base*base%mod,index>>1,mod)*power(base,index&1,mod)))%mod;}
template<typename T>T lowbit(T n){return n&-n;}
template<typename T>T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<typename T>T lcm(T a,T b){return(a!=0||b!=0)?a/gcd(a,b)*b:(T)0;}
const uint N = 400000;bol s[N+1][265];
ullt myRand(ullt &k1,ullt &k2){ullt k3=k1,k4=k2;k1=k4;k3^=(k3<<23);k2=k3^k4^(k3>>17)^(k4>>26);return k2+k4;}
voi gen(uint n,ullt a1,ullt a2){for(uint i=0;i<n;i++)for(uint j=0;j<256;j++)s[i][j]=(myRand(a1,a2)&(1ull<<32))?1:0;}
usint Count[66005];ullt Turn[150];
struct my_bitset
{
ullt A,B,C,D;
my_bitset():A(0),B(0),C(0),D(0){}
my_bitset(bol*T){A=B=C=D=0;for(uint i=0;i<64;i++)A=(A<<1)|T[i];for(uint i=64;i<128;i++)B=(B<<1)|T[i];for(uint i=128;i<192;i++)C=(C<<1)|T[i];for(uint i=192;i<256;i++)D=(D<<1)|T[i];}
my_bitset(chr*T)
{
A=B=C=D=0;
for(uint i=0;i<16;i++)A=(A<<4)|Turn[(uint)T[i]];for(uint i=16;i<32;i++)B=(B<<4)|Turn[(uint)T[i]];
for(uint i=32;i<48;i++)C=(C<<4)|Turn[(uint)T[i]];for(uint i=48;i<64;i++)D=(D<<4)|Turn[(uint)T[i]];
}
usint get(uint p){return((p<8)?((p<4)?(D>>(p<<4)):(C>>((p&3)<<4))):((p<12)?(B>>((p&3)<<4)):(A>>((p&3)<<4))))&65535;}
my_bitset operator^(my_bitset b){return b.A^=A,b.B^=B,b.C^=C,b.D^=D,b;}
voi chg(){A=~A,B=~B,C=~C,D=~D;}
usint count()
{
return
Count[A&65535]+Count[(A>>16)&65535]+Count[(A>>32)&65535]+Count[(A>>48)&65535]+Count[B&65535]+Count[(B>>16)&65535]+Count[(B>>32)&65535]+Count[(B>>48)&65535]+
Count[C&65535]+Count[(C>>16)&65535]+Count[(C>>32)&65535]+Count[(C>>48)&65535]+Count[D&65535]+Count[(D>>16)&65535]+Count[(D>>32)&65535]+Count[(D>>48)&65535];
}
};
my_bitset B[400005],Q;
std::vector<uint>V[25][66005];
chr C[105];
int main()
{
for(usint i=1;i;i++)Count[i]=Count[i>>1]+(i&1);
uint n,m,k;ullt a1,a2;bol ok=false;scanf("%u%u%llu%llu",&n,&m,&a1,&a2),gen(n,a1,a2);
for(uint i=0;i<n;i++){B[i]=s[i];for(uint j=0;j<16;j++)V[j][B[i].get(j)].push_back(i);}
for(uint i=0;i<10;i++)Turn[i+'0']=i;
for(uint i=0;i<6;i++)Turn[i+'A']=10+i;
while(m--)
{
scanf("%s%u",C,&k),Q=my_bitset(C);
if(ok)Q.chg(),ok=false;
for(uint i=0;i<16&&!ok;i++)
{
std::vector<uint>&W=V[i][Q.get(i)];
for(uint p=W.size()-1;~p;p--)if((B[W[p]]^Q).count()<=k){ok=true;break;}
}
puts(ok?"1":"0");
}
return 0;
}
后记
谔,希望不要有卡常题了QAQ
放张图,参见。
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/Luogu-solution-p7738.html