5358: [Lydsy1805月赛]口算训练
Time Limit: 5 Sec Memory Limit: 512 MB
Submit: 318 Solved: 105
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
HINT
Source
然后对于每个质数开棵线段树。
d = (p1^c1)(p2^c2)……(pk^ck),
查询的时候只用查询d的每个质数在[L,R]范围内出现次数是否大于d中次数就行
AC代码:
# include <iostream> # include <cstdio> # include <cstring> # include <vector> # include <algorithm> using namespace std; const int N = 1e5; vector<pair<int,int> > t[N + 5]; int prime[N + 5],cnt,root[N + 5],lc[N * 100],rc[N * 100],s[N * 100],p,a[N + 5];bool vis[N + 5]; void shai() { for(int i = 2;i <= N;i++) { if(!vis[i])prime[++cnt] = i; for(int j = 1;j <= cnt;j++) { if(i * prime[j] > N)break; vis[i * prime[j]] = true; if(i % prime[j] == 0)break; } } for(int i = 1;i <= cnt;i++) for(int j = prime[i];j <= N;j += prime[i]) { t[j].push_back(make_pair(prime[i],j / prime[i])); } } void updata(int &k,int L,int l,int r,int d) { if(!k){k = ++p;lc[k] = rc[k] = s[k] = 0;} s[k] += d; if(l == r)return; int mid = l + r >> 1; if(L <= mid)updata(lc[k],L,l,mid,d); else updata(rc[k],L,mid + 1,r,d); } int Query(int &k,int L,int R,int l,int r) { if(!k)return 0; if(L <= l && r <= R)return s[k]; int mid = l + r >> 1; if(L > mid)return Query(rc[k],L,R,mid + 1,r); if(R <= mid)return Query(lc[k],L,R,l,mid); return Query(lc[k],L,R,l,mid) + Query(rc[k],L,R,mid + 1,r); } int n,m; int main() { shai();int Case; scanf("%d",&Case); while(Case--) { memset(root,0,sizeof root);p = 0; scanf("%d %d",&n,&m); for(int i = 1;i <= n;i++) { scanf("%d",&a[i]); for(int j = 0;j < (int)t[a[i]].size();j++) updata(root[t[a[i]][j].first],i,1,n,t[a[i]][j].second); } int x,y,z; while(m--) { scanf("%d %d %d",&x,&y,&z);bool f = true; for(int j = 0;j < (int)t[z].size();j++) if(Query(root[t[z][j].first],x,y,1,n) < t[z][j].second){f = false;break;} if(f)puts("Yes");else puts("No"); } } }