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 }
代码

 

 

 

posted @ 2017-11-05 14:58  拿叉插猹哈  阅读(218)  评论(0编辑  收藏  举报