Processing math: 100%

HDU4777 Rabbit Kingdom

 
这道题题目挺容易看懂的,其实难度也不是很大,但是我竟然用了一个晚上+半个上午做这道题。
首先,我们可以预处理出对于每个数,他左边第一个与他不互质的数的位置和他右边第一个与他不互质的数的位置。
处理方法:
我们先线筛,在线筛的同时记录筛每个数的那个质因子(from)。
然后我们按照编号从小到达处理每一个数,用f[i]记录当前是i的倍数的最靠右的数的编号。
我们每用from找到一个质因子,就把f[i]和当前的数的编号pos之间的关系处理好。
具体代码:

int f[maxn];
void get_p(int x,int pos) {
  if(x==1) return ;
  int y;
  do {
    y=from[x];
    node[pos].x[1]=max(node[pos].x[1],f[y]);//更新pos左边第一个与他不互质的数
    node[f[y]].x[2]=min(node[f[y]].x[2],pos);//更新f[y]右边第一个与他不互质的数
    f[y]=pos;while(x%y==0) x/=y;
  }while(x!=1);
}

然后就是怎么利用这些东西的问题了。
我们用x[0]表示数的编号(位置),x[1]表示左边第一个与他不互质的数的位置,x[2]表示右边第一个与他不互质的数的位置。
这是一个三维的问题。我们需要找到满足lx0rx1<lx2>r的数的个数。
因为x1<x0<x2,所以我们可以降维。
怎么降维呢?准确来说就是按照容斥列式子:
   [x1<llx0rx2>r]
=[lx0r]  [lx0rx1l]  [lx0rx2r]  +[lx0rx1lx2r]
=[lx0r]  ([x0rx1l][x0<lx1l])  ([lx0x2r][x0>rx2r])  +[x1lx2r]
=[lx0r]  [x0rx1l]  [lx0x2r]  +[x1lx2r]
然后直接用树状数组算这3个东西就可以了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=2e5+10;
int n,m,ans[maxn];
 
int aa;char cc;
int read() {
    aa=0;cc=getchar();
    while(cc<'0'||cc>'9') cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    return aa;
}
 
struct Node{
    int x[3];
}node[maxn];
bool cmp1(const Node& a,const Node& b) {
    return a.x[2]<b.x[2];
}
struct Ask {
    int x[3];
}ask[maxn];
bool cmp2(const Ask& a,const Ask& b) {
    return a.x[2]<b.x[2];
}
 
int prime[maxn/5],totp,from[maxn];
bool ok[maxn];
void get_prime() {
    for(int i=2;i<=maxn-5;++i) {
        if(!ok[i]) prime[++totp]=i,from[i]=i;
        for(int j=1;j<=totp&&prime[j]<=(maxn-5)/i;++j) {
            ok[i*prime[j]]=1;from[i*prime[j]]=prime[j];
            if(i%prime[j]==0) break;
        }
    }
}
 
int f[maxn];
void get_p(int x,int pos) {
    if(x==1) return ;
    int y;
    do {
        y=from[x];
        node[pos].x[1]=max(node[pos].x[1],f[y]);
        node[f[y]].x[2]=min(node[f[y]].x[2],pos);
        f[y]=pos;while(x%y==0) x/=y;
    }while(x!=1);
}
 
int sz[maxn];
void add(int pos) {while(pos<=n+1) sz[pos]++,pos+=(pos&-pos);}
int q(int pos) {int rs=0; while(pos) rs+=sz[pos],pos-=(pos&-pos); return rs;}
 
int main() {
    n=read();m=read();
    get_prime();int x,pos;
    while(n||m) {
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;++i) {
            node[i].x[1]=0;node[i].x[2]=n+1;node[i].x[0]=i;
            x=read(); get_p(x,i);
        }
        for(int i=1;i<=m;++i) {
            ask[i].x[1]=read();ask[i].x[2]=read();
            ask[i].x[0]=i;ans[i]=ask[i].x[2]-ask[i].x[1]+1;
        }
        sort(ask+1,ask+m+1,cmp2);
        memset(sz,0,sizeof(sz));pos=1;
        for(int i=1;i<=m;++i) {
            x=ask[i].x[0];
            while(pos<=n&&node[pos].x[0]<=ask[i].x[2]) add(node[pos].x[1]+1),pos++;
            ans[x]-=(pos-1-q(ask[i].x[1]));
        }
        sort(node+1,node+n+1,cmp1);
        memset(sz,0,sizeof(sz));pos=1;
        for(int i=1;i<=m;++i) {
            x=ask[i].x[0];
            while(pos<=n&&node[pos].x[2]<=ask[i].x[2]) add(node[pos].x[0]+1),pos++;
            ans[x]-=(pos-1-q(ask[i].x[1]));
        }
        memset(sz,0,sizeof(sz));pos=1;
        for(int i=1;i<=m;++i) {
            x=ask[i].x[0];
            while(pos<=n&&node[pos].x[2]<=ask[i].x[2]) add(node[pos].x[1]+1),pos++;
            ans[x]+=(pos-1-q(ask[i].x[1]));
        }
        for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
         
        n=read();m=read();
    }
    return 0;
}

  

 
posted @   shixinyi  阅读(225)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
阅读排行:
· 历时 8 年,我冲上开源榜前 8 了!
· 物流快递公司核心技术能力-海量大数据处理技术
· 四大AI编程工具组合测评
· 关于能否用DeepSeek做危险的事情,DeepSeek本身给出了答案
· 如何在 Github 上获得 1000 star?
点击右上角即可分享
微信分享提示