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

其实大概推一推式子就能得到一个信息,就是答案一定是$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. 安装nvm管理不同的node版本

    在工作或者学习中,偶尔会遇到需要切换不同node版本的需求,幸好有神器nvm可以帮我们解决问题.下面我们就来讲解如何在window系统上安装nvm!

  2. 鼠标悬浮控制元素隐藏与显示 - css中鼠标的hover状态

    需求:当鼠标移动到一个元素A身上时,另外一个元素B显示. 实现原理: A元素与B元素有一个相同的父级. B元素默认隐藏,A元素默认显示. 当鼠标移动到A元素身上时,也可以看做是移动到了A元素的父级身上 ...

  3. ngnix https

    server {            listen       80;#端口号        server_name  www.xxxx.net;#本机                charset ...

  4. Android开发工具Android Studio、Android SDK和Genymotion完全配置

    所谓“工欲善其事,必先利其器”.Android Studio 是谷歌推出一个Android集成开发工具,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提 ...

  5. [Android] Linux下JNI简单实现过程

    大概梳理了一下JNI的过程: start->先写好A.java文件,里面添加native方法B,调用库C.so->编译成.class文件->用javac生成.h文件,文件包含Java ...

  6. Django组件扩展 总结

    1. Form组件扩展: 验证用户输入 obj = Form(reuest,POST,request.FILES) if obj.is_valid(): obj.clean_data else: ob ...

  7. python常用模块之-random模块

    random模块顾名思义就是生成随机数的模块. random模块有以下常见方法: 1,打印0-1之间的任意随机浮点数,不能指定区间. print(random.random()) 2,打印随机符点数, ...

  8. jboss eap6.1(4)(部署应用)

    1.添加应用war包 手动部署,添加war包到standalone\deployments下,手工创建一个文件,如war包名称是a.war,创建一个a.war.deployed文件,内容随意. 2.  ...

  9. 邮件客户端修改密码—OWA

    邮件客户端修改密码—OWA 1.登录OWA 2.输入用户名 3.点击选项 4.更改密码

  10. October 24th, 2017 Week 43rd Tuesday

    We can't give up trying. The fight was worth it. 我们不能放弃尝试,奋斗是值得的. When doing researches in some cutt ...