听说LOJ传了THUSC题赶紧上去看一波

随便点了一题都不会做想了好久才会写暴力爆了一发过了...

LOJ #2978


题意

$ T$次询问,每次询问$ L,R$,问有多少种选取区间中数的方案使得选出的数的积为完全平方数

$ T \leq 100,R \leq 10^7 \sum\limits R-L \leq 6·10^7$

时限$ 5s$


题解

随便写个暴力发现答案都是$2$的若干次幂

首先对于每个数,每个质因子出现的次数显然只有奇偶性是有用的

用一个$ bitset$存储每个数中每个质因数的出现次数的奇偶性

则问题转化成取若干个数使得异或和为$ 0$

用线性基维护这个问题

答案则为$ 2^{自由基的数量}$

其中自由基就是可以被其他基所表示的基

直接这么暴力复杂度太大

考虑若一个质因数的平方超过$ 10^7$那它不可能在一个数中出现两次

因此我们只统计前$ \sqrt{10^7}$个数中的质因数(446个)的$ bitset$

统计答案的时候我们先将区间内数按其最大质因数排序(若一个数的最大质因数不超过 $\sqrt{10^7}$则认为是0)

对于一段最大质因数相同的区间,我们钦定第一个数为非自由基

则这段区间的其他拥有这个质因数的数可以异或上这个钦定的非自由基

以起到消掉这个额外质因数的效果

这样暴力做的复杂度是$ O(6·10^7·450·\frac{450}{64})$的

显然过不了

如果加个剪枝:若当前线性基已满则直接跳出判断 就能过了...

虽然跑的超级慢...

这题有个科技:

若$ R-L+1$超过了一个定值(可定为$ 2 \sqrt{10^7}$),则对每个质数,我们只要选一个数作为这个数的基底

然后所有其他非基底的区间中的数都能被这些基底表示

即答案为$ 2^{R-L+1-出现过的质数数量}$

然后就跑的飞快了...


代码

去掉Solve就是暴力

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<bitset>
#define p 998244353
#define file(x)freopen(x".in","r",stdin);freopen(x".out","w",stdout)
#define rt register int
#define l putchar('\n')
#define ll long long
#define r read()
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans,val=;
bool pri[];int ss[],id[],lp[],zs[],tot;
bitset<>a[];
int q[],sl;
bitset<>make(int x){
bitset<>A;
if(lp[x])x/=lp[x];
for(rt i=;ss[i]*ss[i]<=x&&i<=cnt;i++)while(x%ss[i]==)
A.flip(i),x/=ss[i];
if(x>)A.flip(id[x]);
return A;
}
vector<int>jw[];
void solve(int L,int R){
int gs=R-L+;
for(rt i=;i<=tot&&zs[i]<=R;i++)if(R/zs[i]!=(L-)/zs[i])gs--;
int ans=;
for(rt x=,i=gs;i;i>>=,x=1ll*x*x%p)if(i&)
ans=1ll*ans*x%p;writeln(ans);
}
int main(){
n=r;if(n<=)val=;
const int v=sqrt(val);
for(rt i=;i<=val;i++)if(!pri[i]){
if(i<=v)ss[++cnt]=i,id[i]=cnt;
zs[++tot]=i;
if(i<=v)for(rt j=i*i;j<=val;j+=i)pri[j]=;
if(i>v)for(rt j=i;j<=val;j+=i)lp[j]=i;
}
bitset<>now;
while(n--){
memset(a,,sizeof(a));
int L=r,R=r,ans=;int len=;
if(R-L>){
solve(L,R);
continue;
}
for(rt i=L;i<=R;i++)if(lp[i]<=)jw[lp[i]].push_back(i);
for(rt i=L;i<=R;i++)if(lp[i]<=){
for(rt j=;j<jw[lp[i]].size();j++)q[++len]=jw[lp[i]][j];
jw[lp[i]].clear();
}
sl=;now&=;
for(rt i=;i<=len;i++){
const int v=q[i];
if(lp[v]!=lp[q[i-]]&&i>)now=make(v);
else {
if(sl==cnt){ans=1ll*ans*%p;continue;}
bitset<>g=make(v)^now;
if(g.count()==){ans=1ll*ans*%p;continue;}
for(rt j=;j>=;j--)if(g[j]){
if(a[j][j]){
if(g==a[j]){ans=1ll*ans*%p;break;}
g^=a[j];
}
else {a[j]=g;sl++;break;}
}
}
}
writeln(ans);
}
return ;
}

LOJ #2978「THUSCH 2017」杜老师的更多相关文章

  1. LOJ 2978 「THUSCH 2017」杜老师——bitset+线性基+结论

    题目:https://loj.ac/problem/2978 题解:https://www.cnblogs.com/Paul-Guderian/p/10248782.html 第 i 个数的 bits ...

  2. loj#2978. 「THUSCH 2017」杜老师(乱搞)

    题面 传送门 题解 感谢yx巨巨 如果一个数是完全平方数,那么它的所有质因子个数都是偶数 我们把每一个数分别维护它的每一个质因子的奇偶性,那么就是要我们选出若干个数使得所有质因子的个数为偶数.如果用线 ...

  3. @loj - 2977@ 「THUSCH 2017」巧克力

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 「人生就像一盒巧克力,你永远不知道吃到的下一块是什么味道.」 明 ...

  4. LOJ 2980 「THUSCH 2017」大魔法师——线段树

    题目:https://loj.ac/problem/2980 线段树维护矩阵. 然后是 30 分.似乎是被卡常了?…… #include<cstdio> #include<cstri ...

  5. LOJ 2979 「THUSCH 2017」换桌——多路增广费用流

    题目:https://loj.ac/problem/2979 原来的思路: 优化连边.一看就是同一个桌子相邻座位之间连边.相邻桌子对应座位之间连边. 每个座位向它所属的桌子连边.然后每个人建一个点,向 ...

  6. LOJ 2997 「THUSCH 2017」巧克力——思路+随机化+斯坦纳树

    题目:https://loj.ac/problem/2977 想到斯坦纳树.但以为只能做 “包含一些点” 而不是 “包含一些颜色” .而且不太会处理中位数. 其实 “包含一些颜色” 用斯坦纳树做也和普 ...

  7. LOJ#2977. 「THUSCH 2017」巧克力(斯坦纳树+随机化)

    题目 题目 做法 考虑部分数据(颜色较少)的: 二分中位数\(mid\),将\(v[i]=1000+(v[i]>mid)\) 具体二分操作:然后求出包含\(K\)种颜色的联通快最小的权值和,判断 ...

  8. 「THUSCH 2017」大魔法师 解题报告

    「THUSCH 2017」大魔法师 狗体面太长,帖链接了 思路,维护一个\(1\times 4\)的答案向量表示\(A,B,C,len\),最后一个表示线段树上区间长度,然后每次的操作都有一个转移矩阵 ...

  9. LOJ 2288「THUWC 2017」大葱的神力

    LOJ 2288「THUWC 2017」大葱的神力 Link Solution 比较水的提交答案题了吧 第一个点爆搜 第二个点爆搜+剪枝,我的剪枝就是先算出 \(mx[i]\) 表示选取第 \(i \ ...

随机推荐

  1. Qt class

    Help on class Qt in module PyQt5.QtCore: class Qt(sip.simplewrapper) |  Method resolution order: |   ...

  2. JDBC 初识

    JDBC是 "Java Database Connective" 的缩写,是使用Java去连接数据库进行数据操作的过程. 首先通过Eclipse 创建动态项目,Dynamic We ...

  3. 软工+C(11): 从命令行开始逐步培养编程能力(Java)

    上一篇:助教指南,持续更新... // Version: 0.0.4 许多人,所不知道的是,每一种编程语言都有其对应的单元测试框架,对程序在不同阶段的测试环节也概念模糊.在实际动手编写程序许久之后才听 ...

  4. Commons-DbUtils

    <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils& ...

  5. cordova的常用命令

    常用命令 npm install -g cordova // 加载cordovecordova create MyApp //创建一个新的文件夹cd MyApp //找到当前目录cordova pla ...

  6. NLP语义匹配

    参考资料 [搜狗语义匹配技术前沿]https://www.jiqizhixin.com/articles/2018-10-25-16?from=synced&keyword=%E6%90%9C ...

  7. ueditor 回显html样式会直接出来,无效

    百度了好久,后面发现可以直接这样

  8. CSS绝对定位元素居中的几种方法

    转载自-CSS居中绝对https://www.cnblogs.com/skura23/p/6530556.html 作者:PajamaCat 1,div宽度未知1 <body> <d ...

  9. Netty 客户端断线重连

    client 关闭后会执行 finally 代码块,可以在这里可以进行重连操作 public class NettyClient implements Runnable { private final ...

  10. Nmap小技巧——探测大网络空间中的存活主机

    Nmap快速探测空间主机是否存活的技巧(来自lijiejie师傅): nmap -v -sn -PE -n --min-hostgroup --min-parallelism -oX nmap_out ...