noip模拟题11.17 距noip2016还剩一天
2016-11-17 15:12
260 查看
T1 素数密度
很容易想到一个性质:一个数 n 如果没有小于√n 的因子,那么这个数肯定是素数。那么我们可以先打一个1-√R 的素数表,枚举素数,小于 L 的数中最大的枚举的素数的倍数,然后依次往后筛掉这个素数的倍数。
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #ifdef WIN32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; long long tot,judge[50005],vis[2000005]; long long prime[50005]; int main() { freopen("prime.in","r",stdin); freopen("prime.out","w",stdout); long long l,r,ans=0;scanf(AUTO,&l);scanf(AUTO,&r); for(long long i=2;i*i<=r;i++) { if(!judge[i]) prime[++tot]=i; for(int j=1;j<=tot;j++) { if(i*prime[j]>sqrt(r))break; judge[i*prime[j]]=1; if(i%prime[j]==0)break; } }//线性筛素数 for(long long k=1;k<=tot;k++) { long long tmp=l/prime[k]; long long i=tmp*prime[k]; for(long long j=i;j<=r;j+=prime[k]) if(j<46350&&j==prime[k])continue; else if(j>=l) vis[j-l]=1; } for(long long i=l;i<=r;i++) if(!vis[i-l]) ans++; printf(AUTO,ans); return 0; }
T2 数页码
我居然在考场上写对了一道dp题!!!!!!
祝贺!!!!!!!
dp[i][j] 表示目前的数有 j+1 位,最大位的数字为 i 的所有方案数,那么很明显,举个例子,dp[3][3] 就表示从第 1 页一直到第 3999 页的方案数。
考虑到,比如我们要查 3456 页,那么很明显 dp[3][3] 就算多了,于是我们可以先算第 1 页到第 3000 页,也就是 dp[2][3]+1,然后加上后 456 页中的 3(因为页码是3456,算后面三位数的时候要加上之前没算的千位3),也就是加上 3*456,然后再算 456,也就是 dp[3][2]+1……以此类推,注意只有一位的特殊情况。
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #ifdef WIN32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; long long dp[15][15],op[15]; int main() { freopen("count.in","r",stdin); freopen("count.out","w",stdout); int n;scanf("%d",&n); for(int i=0;i<=9;i++) dp[i][0]=i+dp[i-1][0]; int qp=10; for(int i=1;i<=12;i++) { op[i]=qp; qp*=10; } int t=n,wei=0,ac=1; while(t) { ac*=10; wei++; t/=10; } ac/=10; if(wei==1){printf("%d",dp [0]);return 0;} for(int i=1;i<=wei;i++) for(int j=1;j<=9;j++) { if(j==1) dp[j][i]=dp[9][i-1]*2+j*op[i]+dp[j-1][i]; else dp[j][i]=dp[9][i-1]+j*op[i]+dp[j-1][i]; } long long ans=0,qte=1,tot=0; while(ac) { int tmp=(n/ac)-1; if(tmp>0&&ac>1) { ans+=dp[tmp][wei-1]+tmp+1; ans+=(tmp+1)*(n-(tmp+1)*ac); } else if(tmp==0&&ac>1) { ans+=dp[9][wei-2]+tmp+1; ans+=(tmp+1)*(n-(tmp+1)*ac); } else if(ac==1) ans+=dp[tmp+1][wei-1]; n=n-(tmp+1)*ac;ac/=10;wei--; } printf(AUTO,ans); return 0; }
T3 矩形
Description
胜负胸中料已明,又从堂上出奇兵。秋实大哥是一个下棋好手,独孤求败的他觉得下棋已经无法满足他了,他开始研究一种新的玩法。在一个n×m的棋盘上,放置了k个车,并且他在棋盘上标出了q个矩形,表示矩形内部是战略要地。
d47c
秋实大哥要求一个矩形内的每一个格子,都至少能被一辆在矩形内的车攻击到,那么这个矩形就是被完整保护的。
现在秋实大哥想知道每一个矩形是否被完整保护。
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 31 1
3 2
2 3
2 3 2 3
2 1 3 3
1 2 2 3
Sample Output
YESYES
NO
10000×10000的数组开不下。
用vector保存每一列上的点、每一行上的点。每次查询一个矩阵的时候,这个矩阵被保护,当且仅当每一行都有车或者每一列都有车。那么我们可以对于矩阵的每一行用二分查询是否有在矩阵内的车,如果查询到一行没有,(小优化)直接跳到查询每一列是否有在矩阵内的车。如果到最后一行(列)一直都有,说明这个矩阵被保护,否则不被。
能过60%的数据,正解用什么扫描线+线段树…我是废人。= =
#include<set> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> using namespace std; vector<int>lie[100005]; vector<int>hang[100005]; int visx[100005],visy[100005],tot1,tot2,qu1[100005],qu2[100005]; inline int read() { int 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();} return x*f; } inline bool findx(int k,int last,int top) { if(lie[k].size()==0)return false; if(lie[k].size()==1) { if(lie[k][0]<=top&&lie[k][0]>=last)return true; else return false; } int l=0,r=lie[k].size()-1; do { int mid=(l+r)>>1; if(lie[k][mid]<=top&&lie[k][mid]>=last)return true; else if(lie[k][mid]>top) r=mid; else if(lie[k][mid]<last) l=mid+1; }while(l<r); for(int i=l-1;i<=l+1;i++) if(lie[k][i]<=top&&lie[k][i]>=last)return true; return false; } inline bool findy(int k,int last,int top) { if(hang[k].size()==0)return false; if(hang[k].size()==1) { if(hang[k][0]<=top&&hang[k][0]>=last)return true; else return false; } int l=0,r=hang[k].size()-1; do { int mid=(l+r)>>1; if(hang[k][mid]<=top&&hang[k][mid]>=last)return true; else if(hang[k][mid]>top) r=mid; else if(hang[k][mid]<last) l=mid+1; }while(l<r); for(int i=l-1;i<=l+1;i++) if(hang[k][i]<=top&&hang[k][i]>=last)return true; return false; } inline bool judge(int x1,int y1,int x2,int y2) { for(int i=x1;i<=x2;++i) { if(!findx(i,y1,y2)) break; if(i==x2) return true; } for(int i=y1;i<=y2;++i) if(!findy(i,x1,x2)) return false; return true; } int main() { freopen("brother.in","r",stdin); freopen("brother.out","w",stdout); int n=read(),m=read(),k=read(),q=read(); for(int i=1;i<=k;++i) { int x=read(),y=read(); lie[x].push_back(y); if(!qu1[x]) { visx[++tot1]=x; qu1[x]=1; } hang[y].push_back(x); if(!qu2[y]) { visy[++tot2]=y; qu2[y]=1; } } sort(visx+1,tot1+1+visx); sort(visy+1,tot2+1+visy); for(int i=1;i<=tot1;++i) sort(lie[visx[i]].begin(),lie[visx[i]].end()); for(int i=1;i<=tot2;++i) sort(hang[visy[i]].begin(),hang[visy[i]].end()); for(int i=1;i<=q;i++) { int x1=read(),y1=read(),x2=read(),y2=read(); if(judge(x1,y1,x2,y2))printf("YES\n"); else printf("NO\n"); } return 0; }
相关文章推荐
- noip模拟题11.16 距noip2016还剩两天
- NOIP2016小结
- [noip2016]天天爱跑步(主席树+lca)
- 【NOIP 2016 提高组】换教室
- NOIP2016普及组T3海港解题报告
- noip2016 游记
- 【NOIP2016提高A组模拟9.17】小a的强迫症
- bzoj 4719: [Noip2016]天天爱跑步【树上差分+dfs】
- [NOIp2016] 蚯蚓
- ☆ [NOIp2016] 天天爱跑步 「树上差分」
- 【NOIP2016提高A组模拟9.17】序列
- [NOIP2016]天天爱跑步(树上差分+线段树合并)
- 【JZOJ4791】【NOIP2016提高A组模拟9.21】矩阵
- BZOJ4719[NOIP2016提高组Day1T2] 天天爱跑步
- 【NOIP2016提高A组模拟9.24】就是乘法
- UOJ261 【NOIP2016】天天爱跑步
- 2016 NOIP第一题 买铅笔
- NOIP 2016 蚯蚓(洛谷 P2827)
- 【NOIP2016】天天爱跑步
- 【NOIP2016提高A组模拟7.17】锦标赛