poj3695&bzoj1853 容斥定理
2015-06-02 00:14
281 查看
容斥定理的几个实际应用:
1、求几个矩形的面积并 题目poj3695
2、求一个区间【l,r】内是a1、a2、—-an倍数的数的总数 题目bzoj 1853
3、求一个区间[l,r]与m互质的数的个数
(第三点区间个数为r-l+1,先将m分解质因数a1,a2—an个,求出区间[l,r]内是a1,a2—an倍数的数的总数sum,r-l+1-sum即所与m互质的数的总数) 题目poj1091
poj3695
题意:给出n个矩形,每次询问若干个矩阵的面积并。
在这里由于线段树太伤了,所以就不用这个方法了~~改用面积并。
遍历一次并操作,维护符合的询问即可
bzoj 1853
题意:求若干幸运数在一个区间的倍数的总数
很明显是容斥定理
这里要注意,生成的数先优化一下,去掉自相为倍数的数
遍历从大到小遍历,可以省去很多无用的遍历
1、求几个矩形的面积并 题目poj3695
2、求一个区间【l,r】内是a1、a2、—-an倍数的数的总数 题目bzoj 1853
3、求一个区间[l,r]与m互质的数的个数
(第三点区间个数为r-l+1,先将m分解质因数a1,a2—an个,求出区间[l,r]内是a1,a2—an倍数的数的总数sum,r-l+1-sum即所与m互质的数的总数) 题目poj1091
poj3695
题意:给出n个矩形,每次询问若干个矩阵的面积并。
在这里由于线段树太伤了,所以就不用这个方法了~~改用面积并。
遍历一次并操作,维护符合的询问即可
#include <map> #include <set> #include <queue> #include <stack> #include <math.h> #include <vector> #include <cstdio> #include <string> #include<string.h> #include <fstream> #include <iostream> #include <algorithm> using namespace std; #define exp 1e-8 #define INF 0x3f3f3f3f #define ll long long #define set(a,b) memset(a,b,sizeof(a)); #define set(a,b) memset(a,b,sizeof(a)); #define for1(a,b) for(int a=1;a<=b;a++)//1---(b) #define for0(a,b) for(int a=0;a<=b;a++)//0---(b) void bug(string st="bug") {cout<<st<<endl;} template<typename __ll> inline void READ(__ll &m){ __ll x=0,f=1;char ch=getchar(); while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} m=x*f; } template<typename __ll> inline void read(__ll &m){READ(m);} template<typename __ll> inline void read(__ll &m,__ll &a){READ(m);READ(a);} template<typename __ll> inline void read(__ll &m,__ll &a,__ll &b){READ(m);READ(a);READ(b);} struct dat { int x1,y1,x2,y2; }d[22]; int s[1111111+10]; int aks[1111111+10]; int n,m,cmd,k; void dfs(int x1=0,int y1=0,int x2=10001,int y2=10001,int deep=0,int flag=-1,int sta=0) { if(x1>=x2||y1>=y2)return ; if(deep==n) { if(sta) //选了 { for1(i,m) if((sta|aks[i])==aks[i]) s[aks[i]]+=flag*(x2-x1)*(y2-y1); } return ; } dfs(x1,y1,x2,y2,deep+1,flag,sta); dfs(max(x1,d[deep+1].x1),max(y1,d[deep+1].y1),min(x2,d[deep+1].x2),min(y2,d[deep+1].y2),deep+1,-flag,sta|(1<<deep)); } int main() { int cas=1; while(scanf("%d %d",&n,&m),n+m) { set(aks,0); set(s,0); for1(i,n)read(d[i].x1,d[i].y1),read(d[i].x2,d[i].y2); for1(i,m) { read(cmd); while(cmd--) { read(k); aks[i]|=(1<<(k-1)); } } dfs(); printf("Case %d:\n",cas++); for1(i,m) printf("Query %d: %d\n",i,s[aks[i]]); printf("\n"); } return 0; }
bzoj 1853
题意:求若干幸运数在一个区间的倍数的总数
很明显是容斥定理
这里要注意,生成的数先优化一下,去掉自相为倍数的数
遍历从大到小遍历,可以省去很多无用的遍历
#include <map> #include <set> #include <queue> #include <stack> #include <math.h> #include <vector> #include <cstdio> #include <string> #include<string.h> #include <fstream> #include <iostream> #include <algorithm> using namespace std; #define exp 1e-8 #define INF 10000000000 #define ll long long #define ull unsigned long long int #define set(a,b) memset(a,b,sizeof(a)); #define set(a,b) memset(a,b,sizeof(a)); #define for1(a,b) for(int a=1;a<=b;a++)//1---(b) #define for0(a,b) for(int a=0;a<=b;a++)//0---(b) void bug(string st="bug") {cout<<st<<endl;} template<typename __ll> inline void READ(__ll &m){ __ll x=0,f=1;char ch=getchar(); while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} m=x*f; } template<typename __ll> inline void read(__ll &m){READ(m);} template<typename __ll> inline void read(__ll &m,__ll &a){READ(m);READ(a);} template<typename __ll> inline void read(__ll &m,__ll &a,__ll &b){READ(m);READ(a);READ(b);} ull num[100000]; ull b[100000]; bool vis[100000]; int cnt=0; int n=0; ull ans=0; ull l,r; void dfs1(ull sum) { if(sum>r)return; num[++cnt]=sum; dfs1(sum*10+6); dfs1(sum*10+8); } void dfs2(int deep=n,int flag=-1,ull sta=1) { if(!deep) //遍历完毕 { if(sta!=1) //如果选择了~~ ans+=flag*(r/sta-(l-1)/sta); return ; } dfs2(deep-1,flag,sta); //不选择 ull tmp=sta/__gcd(sta,num[deep]); if((double)tmp*num[deep]<=r) //加一个条件 dfs2(deep-1,-flag,tmp*num[deep]); //选择 } int main() { read(l,r); dfs1(6); dfs1(8); sort(num+1,num+1+cnt); for1(i,cnt) //一个小小的优化,去掉同倍数的值 if(!vis[i]) { b[++n]=num[i]; for(int j=i+1;j<=cnt;j++) if(num[j]%num[i]==0) vis[j]=1; } for1(i,n) num[i]=b[i]; dfs2(); printf("%lld",ans); return 0; }
相关文章推荐
- jps命令使用
- https
- 6.1学习内容 ndk编程释放内存,C语言中char*添加字符得方法,java二维数组的读取与生成
- iOS NSFileHandle 基本用法介绍
- 总结SSH框架整合基础与需要的jar包
- 像写SQL一样编写Java数据应用-TinySqlDsl
- iOS网络编程开发笔记1—JSON和XML数据解析
- 企业库一全套增删改
- Java-Fork/Join的简单例子
- 甘特图与网络图
- JavaScript Cookies
- [转载]nil,Nil,NULL 和NSNull的小结
- Python Show-Me-the-Code 第 0021题 密码加密
- Generate Parentheses
- JavaScript中replace()方法使用时应该注意的几点
- C++对象模型之编译器如何处理函数返回一个对象
- LeetCode解题报告--ZigZag Conversion
- 遗传算法代码
- myeclipse取消js校验
- opencv & qt study-(2)-打开video& camera