求一個區間裡的一個x,這個x與這區間裡面的所有數都互質
阿新 • • 發佈:2018-12-02
連結:https://ac.nowcoder.com/acm/contest/301/H
來源:牛客網
題描述
小樂樂上了一節數學課,數學老師講的很好,小樂樂聽的也如痴如醉。小樂樂聽了老師的講解,知道了什麼是素數,現在他想做幾個習題。
現在題目來了:
首先我們先定義孤獨的數:在一個區間中的一個數字x,如果他與這個區間中的任何數都互質,那麼他就是孤獨的數。
我們給定一個序列,然後接下來會有多次詢問,對於每次詢問,給定兩個整數l, r,我想知道對於(a[l], a[l + 1], ...., a[r])區間來說中有多少孤獨的數。 分析:戴普 ,現在先當模板
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <vector> const int MaxN = 1e5; using namespace std; int n, m, tot; int a[MaxN + 5], pri[MaxN + 5]; int pre[MaxN + 5], last[MaxN + 5], c[MaxN + 5]; vector <int> V[MaxN + 5View Code], g[MaxN + 5]; int res[MaxN + 5]; bool vis[MaxN + 5]; struct NODE { int l, r, id; bool operator < (const NODE A) const { return l < A.l; } }query[MaxN + 5], seg[MaxN + 5]; bool cmp(NODE A, NODE B) { return A.r < B.r; } void Init() { for (int i = 2; i <= MaxN; i++) {if(!vis[i]) pri[++tot] = i; for (int j = 1; j <= tot && i * pri[j] <= MaxN; j++) { vis[i * pri[j]] = 1; if(i % pri[j] == 0) break; } } for (int i = 1; i <= tot; i++) { for (int j = pri[i]; j <= MaxN; j += pri[i]) V[j].push_back(pri[i]); } } void Add(int x, int w) { if(x == 0) return; for (int i = x; i <= MaxN; i += (i & (-i))) c[i] += w; } int Sigma(int x) { int res = 0; for (int i = x; i > 0; i -= (i & (-i))) res += c[i]; return res; } int main() { Init(); while(~scanf("%d%d", &n, &m)) { memset(c, 0, sizeof(c)); memset(pre, 0, sizeof(pre)); g[n + 1].clear(); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), g[i].clear(); for (int i = 1; i <= n; i++) { if(a[i] == 1) { seg[i].l = 0; } else { int Max = 0; for (int v : V[a[i]]) Max = max(Max, pre[v]); seg[i].l = Max; for (int v : V[a[i]]) pre[v] = i; } } for (int i = 0; i <= MaxN; i++) last[i] = n + 1; for (int i = n; i >= 1; i--) { if(a[i] == 1) seg[i].r = n + 1; else { int Min = n + 1; for (int v : V[a[i]]) Min = min(Min, last[v]); seg[i].r = Min; for (int v : V[a[i]]) last[v] = i; } } for (int i = 1; i <= n; i++) g[seg[i].r].push_back(i); for (int i = 1; i <= m; i++) scanf("%d%d", &query[i].l, &query[i].r), query[i].id = i; sort (query + 1, query + m + 1, cmp); int l = 0; for (int i = 1; i <= m; i++) { while(l + 1 <= n && l + 1 <= query[i].r) { Add(seg[l + 1].l, 1); for (int v : g[l + 1]) { Add(seg[v].l, -1); Add(v, 1); } l++; } res[query[i].id] = query[i].r - query[i].l + 1 - Sigma(query[i].r) + Sigma(query[i].l - 1); } for (int i = 1; i <= m; i++) printf("%d\n", res[i]); } return 0; }
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef unsigned long long ull; typedef long long ll; const int N = 1e5+7; int w[N],l[N],r[N];//l[i],r[i]儲存第i個數的質因子出現的最左位置以及最右位置 vector<int>V[N];//V[i]儲存的是j,其中r[j]=i vector<int>have[N],VPrime;//have[i]儲存的是數字i分解的質因子,VPrime儲存的是[1,200000]的素數 int ans[N];//儲存結果 int flag[N]; struct node { int left,right,id; }p[N]; int cmp(node aa,node bb) { return aa.right<bb.right; } int ar[N]; int lowb(int t) { return t&(-t); } void add(int i,int v) { if(i==0) return; for(;i<N;ar[i]+=v,i+=lowb(i)); } int sum(int i) { int s=0; for(;i>0;s+=ar[i],i-=lowb(i)); return s; } void getHave(int index,int v) { int i=0; while(v>1&&i<VPrime.size()) { if(VPrime[i]*VPrime[i]>v) { have[index].push_back(v); break; } if(i<VPrime.size()&& v%VPrime[i]==0) { have[index].push_back(VPrime[i]); } while(i<VPrime.size()&& v%VPrime[i]==0) { v/=VPrime[i]; } i++; } } bool prime[N]; void init() { int i,j; memset(prime,0,sizeof(prime)); prime[1]=prime[0]=1; for(i=2;i<=N-2;i++) for(j=2;i*j<=N-2;j++) { prime[i*j]=1; } VPrime.clear(); for(i=2;i<=N-2;i++) { if(prime[i]==0) VPrime.push_back(i); } for(i=0;i<N;i++) { have[i].clear(); } for(i=2;i<N;i++) { getHave(i,i); } } void init2(int n)//計算出l陣列,r陣列以及V[] { for(int i=0;i<=n;i++) { V[i].clear(); } memset(l,0,sizeof(l)); memset(r,0,sizeof(r)); memset(flag,0,sizeof(flag)); for(int i=1;i<=n;i++) { int left=0; for(int j=0;j<have[w[i]].size();j++) { left=max(left,flag[have[w[i]][j]]); } l[i]=left; for(int j=0;j<have[w[i]].size();j++) { flag[have[w[i]][j]]=i; } } for(int i=1;i<N;i++)//這裡要初始化為n+1 {flag[i]=n+1;} for(int i=n;i>=1;i--) { int right=n+1; for(int j=0;j<have[w[i]].size();j++) { right=min(right,flag[have[w[i]][j]]); } r[i]=right; for(int j=0;j<have[w[i]].size();j++) { flag[have[w[i]][j]]=i; } } for(int i=1;i<=n;i++) { V[r[i]].push_back(i); } } int main() { int i,j,k; int n,m,t; init(); while(scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0)) { for(i=1;i<=n;i++) { scanf("%d",&w[i]); } init2(n); for(i=1;i<=m;i++) { scanf("%d%d",&p[i].left,&p[i].right); p[i].id=i; } sort(p+1,p+1+m,cmp); memset(ar,0,sizeof(ar)); i=1; for(j=1;j<=m;j++) { while(i<=p[j].right) { add(l[i],1);//將左邊notFit的+1 for(k=0;k<V[i].size();k++) { add(l[V[i][k]],-1);//將左邊跟右邊同時notFit的-1,去掉重複 add(V[i][k],1);//將右邊notFit的+1 } i++; } int notFit=sum(p[j].right)-sum(p[j].left-1); ans[p[j].id]=p[j].right-p[j].left+1-notFit; } for(i=1;i<=m;i++) { printf("%d\n",ans[i]); } } return 0; }View Code