2017 济南考前集训 DAY1.AM
(二分专场 ??)
T1
立方数(cubic)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数。
现在给定一个数P,LYK想要知道这个数是不是立方数。
当然你有可能随机输出一些莫名其妙的东西来骗分,因此LYK有T次询问~
输入格式(cubic.in)
第一行一个数T,表示有T组数据。
接下来T行,每行一个数P。
输出格式(cubic.out)
输出T行,对于每个数如果是立方数,输出“YES”,否则输出“NO”。
输入样例
3
8
27
28
输出样例
YES
YES
NO
数据范围
对于30%的数据p<=100。
对于60%的数据p<=10^6。
对于100%的数据p<=10^18,T<=100。
思路:水题 立方数是具有单调性的
直接二分查找即可。
1 #include <set>
2 #include <cctype>
3 #include <cstdio>
4
5 typedef long long LL;
6
7 int T;
8
9 LL p;
10
11 std::set<int> s;
12
13 inline void read(LL&x) {
14 LL f=1;register char c=getchar();
15 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
16 for(;isdigit(c);x=x*10+c-48,c=getchar());
17 x=x*f;
18 }
19
20 int main(int argc,char**argv) {
21 freopen("cubic.in","r",stdin);
22 freopen("cubic.out","w",stdout);
23
24 scanf("%d",&T);
25
26 while(T--) {
27 read(p);
28
29 LL l=0,r=1000001;
30 while(l+1<r) {
31 LL mid=(l+r)>>1;
32 if(mid*mid*mid<=p) l=mid;
33 else r=mid;
34 }
35 if(l*l*l==p) printf("YES\n");
36 else printf("NO\n");
37 }
38
39 return 0;
40 }
T2
立方数2(cubicp)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数。
LYK还定义了一个数叫“立方差数”,若一个数可以被写作是两个立方数的差,则这个数就是“立方差数”,例如7(8-1),26(27-1),19(27-8)都是立方差数。
现在给定一个数P,LYK想要知道这个数是不是立方差数。
当然你有可能随机输出一些莫名其妙的东西,因此LYK有T次询问~
这个问题可能太难了…… 因此LYK规定P是个质数!
输入格式(cubicp.in)
第一行一个数T,表示有T组数据。
接下来T行,每行一个数P。
输出格式(cubicp.out)
输出T行,对于每个数如果是立方差数,输出“YES”,否则输出“NO”。
输入样例
5
2
3
5
7
11
输出样例
NO
NO
NO
YES
NO
数据范围
对于30%的数据p<=100。
对于60%的数据p<=10^6。
对于100%的数据p<=10^12,T<=100。
思路:有个神奇的公式叫立方差公式
x^3-y^3 =(x-y)*(x^2+xy+y^2)
题目中 说了 两个立方数的差为素数
也就是说 (x-y)*(x^2+xy+y^2) 为素数
所以 x-y 只能为1
也就是 两个相邻的立方数的差为素数 二分即可
ps:考场上 错估二分上界 ,只拿了60
1 #include <cstdio> 2 #include <cctype> 3 4 typedef long long LL; 5 6 LL p; 7 8 inline void read(LL&x) { 9 LL f=1;register char c=getchar(); 10 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 11 for(;isdigit(c);x=x*10+c-48,c=getchar()); 12 x=x*f; 13 } 14 15 int main(int argc,char**argv) { 16 freopen("cubicp.in","r",stdin); 17 freopen("cubicp.out","w",stdout); 18 19 int T; 20 scanf("%d",&T); 21 while(T--) { 22 read(p); 23 LL l=0,r=1000001; 24 while(l+1<r) { 25 LL mid=(l+r)>>1; 26 if(mid*mid*mid-(mid-1)*(mid-1)*(mid-1)<=p) l=mid; 27 else r=mid; 28 } 29 30 if(l*l*l-(l-1)*(l-1)*(l-1)==p) printf("YES\n"); 31 else printf("NO\n"); 32 } 33 34 return 0; 35 }
T3
猜数字(number)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK在玩猜数字游戏。
总共有n个互不相同的正整数,LYK每次猜一段区间的最小值。形如[li,ri]这段区间的数字的最小值一定等于xi。
我们总能构造出一种方案使得LYK满意。直到…… LYK自己猜的就是矛盾的!
例如LYK猜[1,3]的最小值是2,[1,4]的最小值是3,这显然就是矛盾的。
你需要告诉LYK,它第几次猜数字开始就已经矛盾了。
输入格式(number.in)
第一行两个数n和T,表示有n个数字,LYK猜了T次。
接下来T行,每行三个数分别表示li,ri和xi。
输出格式(number.out)
输出一个数表示第几次开始出现矛盾,如果一直没出现矛盾输出T+1。
输入样例
20 4
1 10 7
5 19 7
3 12 8
1 20 1
输出样例
3
数据范围
对于50%的数据n<=8,T<=10。
对于80%的数据n<=1000,T<=1000。
对于100%的数据1<=n,T<=1000000,1<=li<=ri<=n,1<=xi<=n(但并不保证一开始的所有数都是1~n的)。
思路:对于按顺序 的判定性问题 我们可以用二分解决
设 l = 1, r = n ,mid = (l+r)>>1;
如果 前mid中如果出现矛盾 ans则在 1~mid中
否则在 mid+1~n中
二分在第几个判定中出现矛盾
对于检验 按照xi从大到小排序
用并查集维护 是否存在一段区间被另一段区间覆盖
1 #include <cstdio> 2 #include <cctype> 3 #include <algorithm> 4 #define max(x, y) ((x) > (y)? (x) : (y)) 5 #define min(x, y) ((x) < (y)? (x) : (y)) 6 7 const int MAXN=1000010; 8 9 int n,T; 10 11 int fa[MAXN]; 12 13 struct node { 14 int s,t,x; 15 16 friend inline bool operator < (node x,node y) { 17 return x.x>y.x; 18 } 19 }; 20 node e[MAXN],p[MAXN]; 21 22 inline void read(int&x) { 23 int f = 1;register char c = getchar(); 24 for(x = 0;!isdigit(c);c == '-' && (f = -1),c = getchar()); 25 for(;isdigit(c);x = x * 10 + c - 48,c = getchar()); 26 x = x * f; 27 } 28 29 int find(int x) {return x == fa[x] ? x : fa[x]=find(fa[x]);} 30 31 bool check(int k) { 32 int lmn,lmx,rmn,rmx; 33 for(int i = 1; i <= n + 1; ++i) fa[i] = i; 34 for(int i = 1; i <= k; ++i) p[i] = e[i]; 35 std::sort(p + 1,p + 1 + k); 36 37 lmn = lmx = p[1].s; 38 rmn = rmx = p[1].t; 39 for(int i = 2; i <= k; ++i) { 40 if(p[i].x < p[i-1].x) { 41 if(find(lmx) > rmn) return true; 42 for(int j = find(lmn); j <= rmx; ++j) 43 fa[find(j)] = find(rmx+1); 44 lmn = lmx = p[i].s; 45 rmn = rmx = p[i].t; 46 } 47 else { 48 lmn = min(lmn, p[i].s); 49 lmx = max(lmx, p[i].s); 50 rmn = min(rmn, p[i].t); 51 rmx = max(rmx, p[i].t); 52 if(lmx > rmn) return true; 53 } 54 } 55 if(find(lmx) > rmn) return true; 56 return false; 57 } 58 59 int main(int argc,char**argv) { 60 freopen("number.in","r",stdin); 61 freopen("number.out","w",stdout); 62 read(n);read(T); 63 for(int i = 1; i <= T; ++i) 64 read(e[i].s),read(e[i].t),read(e[i].x); 65 66 int l = 0,r = T + 1; 67 while(l + 1 < r) { 68 int mid = (l+r)>>1; 69 if(check(mid)) r = mid; 70 else l = mid; 71 } 72 73 printf("%d\n",r); 74 return 0; 75 }
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现