GYM 101102 J.Divisible Numbers(数论+容斥原理)
2017-03-17 13:59
330 查看
Description
给出一个长度为n的序列,q次查询,每次查询给出区间[l,r]和一个数s,s的二进制从右往左第i位表示i是否出现,统计[l,r]中有多少数可以被s所表示的这些出现的某一个数整除
Input
第一行一整数T表示用例组数,每组用例首先输入两整数n和q分别表示序列长度和查询数,之后n个数a[i]表示该序列,最后q行每行三个整数l,r,s分别表示查询的区间和1~10这十个数是否出现的二进制表示
(1<=n,q<=1e5,1<=a[i]<=1e9,1<=l<=r<=n,1<=s<=1023)
Output
对于每次查询,输出[l,r]中有多少数被出现的这些数中的某一个整除
Sample Input
1
4 2
2 5 3 8
1 3 2
2 4 355
Sample Output
1
3
Solution
枚举这1023种情况,求出每种情况出现的数字的最小公倍数,去重之后只有47种可能,num[i][j]表示a序列前i个数中有多少数可以被这47个数中的第j个整除,对于每次查询,假设出现的数是b[1]~b[res],如果b序列中某个数可以整除另一个,那么把大的数去掉,因为查询大的数没有意义,例如2 4同时出现,那么被4整除的数字一定被2整除,只需要统计被2整除的数字即可,4可以去掉,去掉这些情况后,用容斥定理计数即可,res最多为5,所以整体时间复杂度是O(47n+31q)
Code
给出一个长度为n的序列,q次查询,每次查询给出区间[l,r]和一个数s,s的二进制从右往左第i位表示i是否出现,统计[l,r]中有多少数可以被s所表示的这些出现的某一个数整除
Input
第一行一整数T表示用例组数,每组用例首先输入两整数n和q分别表示序列长度和查询数,之后n个数a[i]表示该序列,最后q行每行三个整数l,r,s分别表示查询的区间和1~10这十个数是否出现的二进制表示
(1<=n,q<=1e5,1<=a[i]<=1e9,1<=l<=r<=n,1<=s<=1023)
Output
对于每次查询,输出[l,r]中有多少数被出现的这些数中的某一个整除
Sample Input
1
4 2
2 5 3 8
1 3 2
2 4 355
Sample Output
1
3
Solution
枚举这1023种情况,求出每种情况出现的数字的最小公倍数,去重之后只有47种可能,num[i][j]表示a序列前i个数中有多少数可以被这47个数中的第j个整除,对于每次查询,假设出现的数是b[1]~b[res],如果b序列中某个数可以整除另一个,那么把大的数去掉,因为查询大的数没有意义,例如2 4同时出现,那么被4整除的数字一定被2整除,只需要统计被2整除的数字即可,4可以去掉,去掉这些情况后,用容斥定理计数即可,res最多为5,所以整体时间复杂度是O(47n+31q)
Code
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; #define INF 0x3f3f3f3f #define maxn 100001 int T,n,q,a[666],c[2525],cnt,num[maxn][50],b[11]; int gcd(int a,int b) { return b?gcd(b,a%b):a; } int lcm(int a,int b) { return a*b/gcd(a,b); } void init() { cnt=0; for(int k=2;k<1024;k+=2) { int temp=1; for(int i=1;i<10;i++) if(k&(1<<i))temp=lcm(temp,i+1); a[cnt++]=temp; } sort(a,a+cnt); cnt=unique(a,a+cnt)-a; printf("cnt=%d\n",cnt); for(int i=0;i<cnt;i++)c[a[i]]=i; } int main() { init(); scanf("%d",&T); while(T--) { scanf("%d%d",&n,&q); memset(num[0],0,sizeof(num[0])); for(int i=1;i<=n;i++) { int temp; scanf("%d",&temp); for(int j=0;j<cnt;j++) { if(temp%a[j]!=0)num[i][j]=num[i-1][j]; else num[i][j]=num[i-1][j]+1; } } while(q--) { int l,r,x,res=0; scanf("%d%d%d",&l,&r,&x); for(int i=0;i<10;i++) if(x&(1<<i))b[res++]=i+1; if(b[0]==1)printf("%d\n",r-l+1); else { for(int i=0;i<res;i++) for(int j=i+1;j<res;j++) if(b[j]%b[i]==0) swap(b[j],b[res-1]),res--,j--; int N=1<<res,ans=0; for(int i=1;i<N;i++) { int temp=1,count=0; for(int j=0;j<res;j++) if(i&(1<<j))temp=lcm(temp,b[j]),count++; if(count&1)ans+=num[r][c[temp]]-num[l-1][c[temp]]; else ans-=num[r][c[temp]]-num[l-1][c[temp]]; } printf("%d\n",ans); } } } return 0; }
相关文章推荐
- Gym - 101102B B. The Little Match Girl 贪心、数论、分步
- Codeforces Round #305 (Div. 2) E题(数论+容斥原理)
- BZOJ 2005: [Noi2010]能量采集( 数论 + 容斥原理 )
- CF 803 F. Coprime Subsequences(数论题,莫比乌斯,容斥原理)
- HDU 2841 Visible Trees(容斥原理,数论)
- 数论(容斥原理)hdu-4059-The Boss on Mars
- 【中国剩余定理】【容斥原理】【快速乘法】【数论】HDU 5768 Lucky7
- 【中国剩余定理】【容斥原理】【快速乘法】【数论】HDU 5768 Lucky7
- Gym 101102D Rectangles 【单调栈】
- GYM 101102 E.Ya Rajaie and Books (水~)
- 一道在网上找不到的T 数论?容斥原理
- Codeforces #305 div2 E. Mike and Foam 数论 容斥原理
- Codeforces839D Winter is here (数论:容斥原理)
- cf/Codeforces Gym 100548F Color (2014年西安站F题) (容斥原理)
- 数论(容斥原理)hdu-4509-The Boss on Mars
- GYM 101102 F.Exchange(水~)
- hdu1695 综合数论 欧拉函数 分解质因子 容斥原理 打印素数表 各种模板
- 数论 毕达哥斯拉三元组 + 欧拉函数 + 容斥原理 hdu3939
- HDU 4135 Co-prime(容斥原理 + 基础数论)
- UVa 11806 Cheerleaders (数论容斥原理)