这是个非常有趣的数学题啦...

其实大概推一推式子就能得到一个信息,就是答案一定是$2$的整数次幂,并且其实答案就是$2^{R-L+1-sum}$,其中$sum$表示有多少个数不能用$L-i-1$的数表达出来。

另外,根据寿司晚宴那道题给予的启发,我们只需要统计质数小于$\sqrt {10^7}$的就可以了,然后打一个表就可以知道,一共大概有$450$个左右。

那么$70$分的部分分就很容易到手了。

我们可以通过$O(n)$的时间复杂度,预处理出$10^7$以内的所有数的最大质因子,显然,每个数大于$\sqrt{10^7}$的质因子最多只有一个。

那么可以分开考虑,如果没有大于$\sqrt{10^7}$的质因子,那么就可以用$bitset$维护一下每个质因子在选取的同时需要选择哪些其他比他大的质因子,以及现在需要选择什么质因子。

然后还有就是需要把所有的在$[L,R]$之内的数,按照最大质因子的大小排序,这样是为了保证在更新到$x$的时候,比$x$小的质因子都已经出现过了,或者不会再出现了,或者出现的时候再来更新答案。

然后每次$O(\frac{450\times 450}{32})$的时间(跑不满,大概均摊下来每次询问的总时间是$O(\frac{450^3}{32})$上下的),来验证能否更新答案,也就是能否被选出了更新答案,具体实现类似高斯消元。

然后如果存在比$\sqrt{10^7}$大的质因子,那么就把这个质因子去掉。

如果没存在过这个质因子,那么把这个数能分解出来的小于$\sqrt{10^7}$的质因子全部记录下来,并且这个数不能用来更新答案。

如果存在过这个质因子,那么上面一定处理过了上一个包含这个质因子的数的小于$\sqrt{10^7}$的质因子,然后用两个$bitset$抑或一下,也就是说这个质因子必须被消掉,然后再重复进行最上面没有大于$\sqrt{10^7}$的质因子的操作即可。

然后这个东西的正确性显然,因为其实所有包含数$x$的能成为完全平方数的方案都是同构的,也就是从某个方案加上一个乘积是完全平方数的方案转移过来的,所有只需要验证一个方案能否满足即可,也就是说能不能通过前面某些不同的质因子把相同的东西完全消去。

这个是$70$分的东西,因为算上排序等操作,一次询问的总时间复杂度是$O(\frac{450^3}{32}+(R-L+1)\log {(R-L+1)}+(R-L+1)\times \frac{500}{32})$的。

这个东西完全没有办法优化了...

然后可以通过一些奇思妙想拿到满分。(其实只需要加上$11,12$测试点的特判就可以了...)

也就是说,如果$R-L+1$的区间大于$2\times \sqrt{10^7}$的话,就会在这段区间内包含全部的$1\sim \sqrt{10^7}$以内的所有质因子,通过消元的话,一定可以得到全部的数字,除非这个数的是质数,并且只在这点区间内只出现一次。

具体证明的话,我也不会很会啊...(因为我复现的时候才写了$70$分啊)

然后就没了...

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
using namespace std;
#define N 10000005
#define ll long long
#define mod 998244353
struct node
{
int x,y;
node(){}
node(int a,int b){x=a,y=b;}
inline bool operator < (const node &a) const {return y==a.y?x<a.x:y<a.y;}
}a[N];
bitset<455>b[455],now,tmp;
int ans,L,R,pri[N],t[N],vis[N],idx[N],cnt,tot,block,size;bool f[N];
void init()
{
t[1]=1;
for(int i=2;i<=10000000;i++)
{
if(!vis[i])pri[++cnt]=i,t[i]=i,idx[i]=cnt,size+=(i<=block);
for(int j=1;j<=cnt&&pri[j]*i<=10000000;j++)
{
vis[pri[j]*i]=1;t[pri[j]*i]=max(pri[j],t[i]);
if(i%pri[j]==0)break;
}
}
}
int get_fac(int x,bitset<455> &now)
{
bool flag=0;now.reset();
if(t[x]>block)x/=t[x];
while(x!=1)
{
int j=t[x],cnt=0;
while(x%j==0)x/=j,cnt++;
if(cnt&1)
{
now[idx[j]]=1;
flag=1;
}
}return flag;
}
int get_now()
{
for(int i=1;i<=size;i++)
if(now[i])
if(b[i][i])now^=b[i];
else return b[i]=now,1;
return 0;
}
int q_pow(int x,int n){int ret=1;for(;n;n>>=1,x=(ll)x*x%mod)if(n&1)ret=(ll)ret*x%mod;return ret;}
int solve(int L,int R)
{
int ret1=0,ret2=0;tot=0;
for(int i=max(2,L);i<=R;i++)a[++tot]=node(i,t[i]);
sort(a+1,a+tot+1);
for(int i=1;i<=size;i++)b[i].reset();
for(int i=1;i<=tot;i++)
{
if(a[i].y<=block)
{
if(ret1<=size)
if(get_fac(a[i].x,now))
ret1+=get_now();
}else if(a[i].y!=a[i-1].y)
{
ret2++;
if(ret1<=size)get_fac(a[i].x,tmp);
}else if(ret1<=size)
{
get_fac(a[i].x,now);
now^=tmp;ret1+=get_now();
}
}
return q_pow(2,R-L+1-ret1-ret2);
}
int solve2(int L,int R)
{
int ret=0;
for(int i=2;i<=R;i++)
if(!vis[i]&&(R/i)>((L-1)/i))ret++;
return q_pow(2,R-L+1-ret);
}
int main()
{
block=sqrt(10000000)+1;
int T;scanf("%d",&T);init();
while(T--)
{
scanf("%d%d",&L,&R);
if(R-L<=100000)printf("%d\n",solve(L,R));
else printf("%d\n",solve2(L,R));
}
}

  

THUSC 2017 D1T2 杜老师的更多相关文章

  1. LOJ #2978「THUSCH 2017」杜老师

    听说LOJ传了THUSC题赶紧上去看一波 随便点了一题都不会做想了好久才会写暴力爆了一发过了... LOJ #2978 题意 $ T$次询问,每次询问$ L,R$,问有多少种选取区间中数的方案使得选出 ...

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

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

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

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

  4. 【THUSC2017】杜老师

    题目描述 杜老师可是要打+∞年World Final的男人,虽然规则不允许,但是可以改啊! 但是今年WF跟THUSC的时间这么近,所以他造了一个idea就扔下不管了…… 给定L,R,求从L到R的这R− ...

  5. THUSC 2017 游记

    Day0 早上在家里整理东西. 下午坐飞机去北京.(怎么又去北京,上周刚去的北京) 一开始飞机爬升的时候太无聊就睡着了.醒了以后就开始吃东西.吐槽一句:厦航的飞机就是好啊.上面的点心也比上次海航的好吃 ...

  6. 【THUSC2017】【LOJ2978】杜老师 高斯消元

    题目大意 给你 \(l,r\),求从 \(l\) 到 \(r\) 这 \(r-l+1\) 个数中能选出多少个不同的子集,满足子集中所有的数的乘积是一个完全平方数. 对 \(998244353\) 取模 ...

  7. 洛谷 P4948 拉格朗日多项式插值(杜老师板子)

    https://www.luogu.org/problemnew/show/P4948 这篇博客主要目的是存一下的dls的神奇板子,本来应该是推公式或者二分做的 但是dls的插值板子直接写好了这个特殊 ...

  8. THUSC 2017 大魔法师

    一个序列,每个物品有三个权值 $A,B,C$ 要求维护: 1.区间 $A_i+=B_i$ 2.区间 $B_i+=C_i$ 3.区间 $C_i+=A_i$ 4.区间 $A_i+=v$ 5.区间 $B_i ...

  9. [THUSC2017]杜老师:bitset+线性基

    算法一(50pts) 分析 有一个很显然的暴力做法,对于区间内的每个数开个bitset,然后暴力分解质因数.如果对于一个数,它的一个质因子的指数是奇数,那么就把bitset的对应位设成\(1\).答案 ...

随机推荐

  1. CentOS7安装mongodb

    1.下载mongodb的*.tar.gz安装包 2.移到centos7中并解压 tar -xzvf mongodb.tar.gz 3.配置环境变量 vim /etc/profile 添加如下内容: # ...

  2. Java基础笔记(3) 进制与进制转换

    ---恢复内容开始--- 进制 在一般生活中,我们一直在应用的十进制,就是逢十进一,而今天我们要接触的是,计算机编程常用的进制!首先我们要知道,计算机内部运算采用的是二进制,也就是逢二进制! 1.什么 ...

  3. froala富文本编辑器与golang、beego,脱离ueditor苦海

    一直用百度的ueditor,可是阿里云这种"wo chuo"的云上部署的beego做的服务,总是出现ueditor.all.min.js语法错误,清理浏览器缓存后又会好起来.本地调 ...

  4. idea常规设置

    java开发目前很多都是使用IntelliJ IDEA这款神器.废话不多说,官网地址:https://www.jetbrains.com/idea/ 我一直都是保持最新版本,安装之后注册. 首先需要安 ...

  5. APP性能测试指标和测试方法

    流量 常用方法 方法一:Android系统自带统计功能(总体流量数值) Proc/uid_stat/{UID}/tcp_snd和tcp_rcv UID是每个app安装时候分配的唯一编号用于识别该app ...

  6. SQL Server存储过程输入参数使用表值

    转载自:http://blog.csdn.net/smithliu328/article/details/9996149 在2008之前如果我们想要将表作为输入参数传递给SQL Server存储过程使 ...

  7. leveldb源码分析--SSTable之block

    在SSTable中主要存储数据的地方是data block,block_builder就是这个专门进行block的组织的地方,我们来详细看看其中的内容,其主要有Add,Finish和CurrentSi ...

  8. 报错:java.net.bindexception: address already in use: jvm_bind:8080

    原因:8080端口被占用 这说明80端口(该端口是Tomcat的监听端口)已经被其他程序占用,先用命令提示符 " netstat -ano " 命令显示端口状态,再在结果中找到端口 ...

  9. TCP的socket资源被耗尽的问题

    一. 故障现象 部分机顶盒用户出现大面积登录APP时,界面停留在登陆页面,无反应. 二. 现象初步分析 本次问题出现时,所有AAA出现了异常流量波动,在AAA异常流量段期间接到用户故障报障.此时主要表 ...

  10. C# 实现 JAVA AES加密解密[原创]

    以下是网上普遍能收到的JAVA AES加密解密方法. 因为里面用到了KeyGenerator 和 SecureRandom,但是.NET 里面没有这2个类.无法使用安全随机数生成KEY. 我们在接收J ...