[NOIP模拟题][数学][乱搞][DP?][扫描线][线段树]
来源:互联网 发布:eclipse使用ubuntu字体 编辑:程序博客网 时间:2024/04/30 05:54
T1
给定区间[ L,R ]{L<=R<=21亿},区间长度<=1e6,求区间内素数个数
看数据范围就知道应该从这个区间入手
想到一个重要的性质,n以内的数最多只有一个大于根号n的质因子,那么我们如果只用根号n以内的素数,一定可以将n以内的素数筛出来
那么就可以先将根号n以内的素数筛出来,再用它们来筛一遍[L,R]即可
#include<cstdio>#include<cstring>#include<cctype>#include<algorithm>#include<cmath>using namespace std;typedef long long LL;const int maxlen=1e6+5;int n,m,prime[maxlen],cnt,len,ans;bool vis[maxlen],mark[maxlen];int readint(){ int x=0; char ch=getchar(); while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();} return x;}void init(){ int lim=(int)sqrt(n+0.5); for (int i=2;i<=lim;i++) { if (!vis[i]) prime[++cnt]=i; for (int j=1;j<=cnt;j++) { int temp=i*prime[j]; if (temp>lim) break; vis[temp]=true; if (i%prime[j]) break; } }}int main(){ freopen("prime.in","r",stdin); freopen("prime.out","w",stdout); m=readint(); n=readint(); len=n-m+1; init(); for (int i=1;i<=cnt;i++) { int k=m/prime[i]; k=k*prime[i]; if (k<=prime[i]) k=prime[i]<<1; if (k<m) k+=prime[i]; for (LL j=k;j<=n;j+=prime[i]) mark[j-m+1]=true; } for (int i=1;i<=len;i++) if (!mark[i]) ans++; printf("%d",ans); return 0;}
T2
对于一个数n,它的贡献为每位上的数值,例如w(123)=1+2+3
求1-n的贡献之和,n<=1e9
没10个数,个位贡献之和为45,每一百个数,十位贡献之和为450,大概就这样随便算就行了
考试时思维很混乱,代码写的丑
#include<cstdio>#include<cstring>#include<cctype>#include<algorithm>#ifdef WIN32#define AUTO "%I64d"#else #define AUTO "%lld"#endif using namespace std;typedef long long LL;const LL val=1+2+3+4+5+6+7+8+9;LL n,flag,ans,last;int readint(){ int x=0; char ch=getchar(); while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();} return x;}int main(){// freopen("count.in","r",stdin);// freopen("count.out","w",stdout); n=readint(); ans+=n/10*val; for (int i=1;i<=n%10;i++) ans+=i; last=n%10; flag=10; LL x=n/10; while (x) { ans+=x/10*flag*val; LL temp=x%10; for (int i=1;i<temp;i++) ans+=i*flag; ans+=temp*(last+1); last=n%(flag*10); flag*=10; x/=10; } printf(AUTO,ans); return 0;}
T3
Description
胜负胸中料已明,又从堂上出奇兵。秋实大哥是一个下棋好手,独孤求败的他觉得下棋已经无法满足他了,他开始研究一种新的玩法。
在一个n×m的棋盘上,放置了k个车,并且他在棋盘上标出了q个矩形,表示矩形内部是战略要地。
秋实大哥要求一个矩形内的每一个格子,都至少能被一辆在矩形内的车攻击到,那么这个矩形就是被完整保护的。
现在秋实大哥想知道每一个矩形是否被完整保护。
Input
第一行包含四个整数n,m,k,q,表示棋盘的大小,车的数量以及矩形的数量。
接来下k行,每行包含两个整数x,y,表示有一辆车位于从左往右第x列,从下往上第y行。
接下来q行,每行包含四个整数x1,y1,x2,y2,表示一个矩形的左下角和右上角坐标。
1≤n,m≤1e5,1≤k,q≤2e5,1≤x1≤x2≤1e5,1≤y1≤y2≤1e5,1≤x≤1e5,1≤y≤1e5。
Output
输出q行,对于每一次询问,这个矩形若被完整保护了输出”YES”,否则输出”NO”。
Sample input
4 3 3 3
1 1
3 2
2 3
2 3 2 3
2 1 3 3
1 2 2 3
Sample Output
YES
YES
NO
Limit
此题无小数据
无小数据是假的,而且裸暴力都有60分
不过暴力还是需要理解题意
那就是想要满足一个矩形被覆盖,必选满足所有横线上有点或所有竖线上有点
那么就可以随便暴力了
我用的是前缀和
下面是正解
首先我们来处理每条横线上有点的情况
以所有纵坐标为结点建一棵线段树,每个结点维护更新当前的横坐标,一段区间即维护横坐标的最小值
那我们以横坐标从左往右扫描,遇到车(x,y)就更新y的x,遇到矩形(x1,y1,x2,y2)的右边界x2就查询区间(y1,y2)横坐标最小值,若最小值大于等于x1,那么矩形是可以被完全覆盖的
不过因为要处理两种情况,代码可能会写的十分冗杂,可以考虑第一次处理横线,然后将车和矩形的横纵坐标翻转,再相同的处理竖线即可
#include<cstdio>#include<cstring>#include<algorithm>#include<cctype>#include<vector>using namespace std;const int N=1e5;int n,m,k,q;bool ans[N<<1|1];int readint(){ int x=0; char ch=getchar(); while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} return x;}struct Square{ int x1,y1,x2,y2,ID; bool operator<(const Square &temp)const { return x2<temp.x2; } void read(int id) { x1=readint(); y1=readint(); x2=readint(); y2=readint(); ID=id; }}square[N<<1|1];struct Car{ int x,y; bool operator<(const Car &temp)const { return x<temp.x; } void read() { x=readint(); y=readint(); }}car[N<<1|1];struct Seg{ int L,R,val;}seg[N<<2];#define Lson (tr<<1)#define Rson (tr<<1|1)void build(int L,int R,int tr){ seg[tr].L=L; seg[tr].R=R; seg[tr].val=0; if (L==R) return ; int mid=(L+R)>>1; build(L,mid,Lson); build(mid+1,R,Rson);}void pushup(int tr){ seg[tr].val=min(seg[Lson].val,seg[Rson].val);}void update(int tr,int pos,int add){ if (seg[tr].L==seg[tr].R) { seg[tr].val=add; return ; } int mid=(seg[tr].L+seg[tr].R)>>1; if (pos<=mid) update(Lson,pos,add); else update(Rson,pos,add); pushup(tr);}int query(int tr,int s,int t){ if (seg[tr].L==s&&seg[tr].R==t) return seg[tr].val; int mid=(seg[tr].L+seg[tr].R)>>1; if (t<=mid) return query(Lson,s,t); if (s>=mid+1) return query(Rson,s,t); return min(query(Lson,s,mid),query(Rson,mid+1,t));}void work(int X,int Y){ build(1,Y,1); sort(car+1,car+k+1); sort(square+1,square+q+1); int posc=1,poss=1; for (int i=1;i<=X;i++) { while (posc<=k&&car[posc].x<=i) update(1,car[posc].y,car[posc].x),posc++; while (poss<=q&&square[poss].x2==i) { int temp=query(1,square[poss].y1,square[poss].y2); if (temp>=square[poss].x1) ans[square[poss].ID]=true; poss++; } }}void reserve(){ for (int i=1;i<=k;i++) swap(car[i].x,car[i].y); for (int i=1;i<=q;i++) swap(square[i].x1,square[i].y1),swap(square[i].x2,square[i].y2);}int main(){ freopen("brother.in","r",stdin); freopen("brother.out","w",stdout); n=readint(); m=readint(); k=readint(); q=readint(); for (int i=1;i<=k;i++) car[i].read(); for (int i=1;i<=q;i++) square[i].read(i); work(n,m); reserve(); work(m,n); for (int i=1;i<=q;i++) if (!ans[i]) puts("NO"); else puts("YES"); return 0;}
- [NOIP模拟题][数学][乱搞][DP?][扫描线][线段树]
- [NOIP模拟题][模拟][DP][乱搞]
- NOIP模拟题 [模拟][DP][线段树]
- [NOIP模拟题][DFS][DP][乱搞]
- 【NOIP模拟题】[状压dp][线段树]
- (转)【NOIP模拟题】【线段树】【扫描线】2016.11.17 第三题 矩形 题解
- [NOIP模拟题][杂题][状压DP][DFS序][线段树]
- 【noip模拟题】[dp][二分][树链剖分][hdu5029][线段树]
- NOIP模拟题 [递推][优化][dp][线段树][离散]
- 10.11 NOIP模拟赛 DP + 线段树 + DP + 单调队列
- BZOJ-3225 立方体覆盖 线段树+扫描线+乱搞
- NOIP模拟题 2016.11.10 [模拟] [状压DP] [线段树] [DFS序]
- NOIP模拟题 2016.11.14 [动态规划] [线段树优化DP] [字符串的复制粘贴DP]
- [NOIP模拟题][DP][水题][数学][树链剖分][差分序列]
- [NOIP模拟][状压dp][dfs序列][线段树]
- 10.4 NOIP模拟赛 线段树+DP+Trie
- [NOIP模拟题][树状数组][线段树]
- 【NOIP 模拟题】[T1](递推+乱搞)
- 为什么display:line-block的a标签会加上文字之后会向下移动呢?
- shiro登录,多个项目session被覆盖问题
- 根据List其中某个属性进行排序
- cpp的策略模式
- 《老码识途:从机器码到框架的系统观逆向修炼之路》- 第1章 - 总结
- [NOIP模拟题][数学][乱搞][DP?][扫描线][线段树]
- linux rz sz
- 工厂方法模式
- Python之列表,字符串,元组,字典,斐波那契数列
- 深度学习库Deep Learning Libraries by Language
- Android图表库MPAndroidChart(六)——换一种思考方式,水平条形图的实现过程
- C++Primer第五版 第一章习题答案(部分)
- 项目实战:说一说运算符优先级和代码可读性
- C++与设计模式(11)——装饰模式