Codeforces Round #561 (Div. 2)

C. A Tale of Two Lands

题意:

  给出 n 个数,问有多少点对(x,y)满足 |x-y| ≤ |x|,|y| ≤ |x+y|;

  (x,y) 和 (y,x) 表示一种答案;

题解:

  数形结合;

  对于某数 x 查找满足条件 y 有多少个;

  ①x ≥ 0

    y ∈ [x/2 , 2x] ∪ [ -2x , -x/2];

  ②x < 0

    y ∈ [2x , -x/2] ∪ [-x/2 , -2x];

  特别注意临界值 x/2 处;

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int maxn=2e5+50;
 5 
 6 int n;
 7 int x[maxn];
 8 
 9 int F(int a,int b)///查找数组x中有多少数位于[a,b]之间
10 {
11     if(a > b)
12         swap(a,b);
13     int t1=lower_bound(x+1,x+n+1,a)-x;
14     int t2=upper_bound(x+1,x+n+1,b)-x;
15     return t2-t1;
16 }
17 ll Solve()
18 {
19     sort(x+1,x+n+1);
20 
21     ll ans=0;
22     for(int i=1;i <= n;++i)
23     {
24         int a,b;
25         if(x[i] >= 0)
26             a=(x[i]+1)/2;
27         else
28             a=(x[i]-1)/2;///不能写成(x[i]-1)>>1;
29         b=x[i]*2;///不能写成b=x[i]<<1;
30         ans += F(a,b);
31         ans += F(-a,-b);
32         ans--;///减掉x[i]本身
33     }
34     return ans>>1;///重复计算,除以2
35 }
36 int main()
37 {
38     scanf("%d",&n);
39     for(int i=1;i <= n;++i)
40         scanf("%d",x+i);
41     printf("%lld\n",Solve());
42 
43     return 0;
44 }
View Code

坑:

  负数使用右移符号出错;

  -2×2 ≠ -2<<1;

  左移,右移只可以用到正整数上;

  负数禁用位移运算;

 


D. Cute Sequences

题意:

  定义“Cute Sequences”,如果序列x满足 ∀i∈[2 , n] xi=xi1+xi2++x1+ri ≤ r≤ m),那么次序列为"Cute Sequences";

  现给出你 a,b,m ,让你构造一个序列,满足:

  ①x[1] = a , x[n] = b;

  ②n ≤ 50;

  ③此序列为"Cute Sequences";

题解:

  定义数组val[]存储最终的值;

  看下面这段代码:

 1 ll sum=a;
 2 ll k=0;
 3 val[++k]=a;
 4 while(k <= 50)
 5 {
 6     if(val[k] >= b)
 7         break;
 8 
 9     val[++k]=sum+m;
10     sum += val[k];
11 }

  因为题目要求 k ≤ 50,所以,要先让其每次加最大的值 m ,找到使得 val[k] ≥ b 的最小的 k ;

  那么多的部分 val[k]-b 该怎么办呢?

   

  刚开始,每个数都会增加 m ,如果第 i 个数少加 x,有什么变化呢?

  先通过上述小范围的数据看一下规律;

  你会发现,如果第 i 个数少加 x,那么,对于第 j (j > i) 个数,就会少加2j-i-1x;

  这样的话,就可以通过前面的数少加 x 使得第 k 个数 val[k] 变为 b;

  不过在此之前你得确定 val[k] 可以减少为 b;

 1 bool isSat(int k)
 2 {
 3     memcpy(tmp+1,val+1,k*sizeof(ll));
 4     for(int i=2;i <= k;++i)
 5     {
 6         ll x=m-1;
 7         tmp[i] -= x;
 8         for(int j=i+1;j <= k;++j)///i之后的数依次减少2^(j-i-1)*x,累加x即可
 9             tmp[j] -= x,x += x;
10         if(tmp[k] <= b)
11             return true;
12     }
13     return tmp[k] <= b ? true:false;
14 }

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define mem(a,b) memset(a,b,sizeof(a))
 5 const int maxn=2e5+50;
 6 
 7 int q;
 8 ll a,b,m;
 9 ll val[60];
10 ll tmp[60];
11 
12 bool isSat(int k)
13 {
14     if(k == 1)
15         return true;
16 
17     memcpy(tmp+1,val+1,k*sizeof(ll));
18     for(int i=2;i <= k;++i)
19     {
20         ll x=m-1;
21         tmp[i] -= x;
22         for(int j=i+1;j <= k;++j)
23             tmp[j] -= x,x += x;
24         if(tmp[k] <= b)
25             return true;
26     }
27     return false;
28 }
29 void Solve()
30 {
31     ll sum=a;
32     ll k=0;
33     val[++k]=a;
34     while(k <= 50)
35     {
36         if(val[k] >= b)
37             break;
38 
39         val[++k]=sum+m;
40         sum += val[k];
41     }
42 
43     if(k > 50 || !isSat(k))
44     {
45         printf("-1\n");
46         return ;
47     }
48 
49     printf("%lld %lld",k,a);
50     for(int i=2;i < k;++i)
51     {
52         ll d=val[k]-b;
53         ll x=min(m-1,d/(1ll*1<<(k-i-1)));
54 
55         val[i] -= x;
56         for(int j=i+1;j <= k;++j)
57             val[j] -= x,x += x;
58 
59         printf(" %lld",val[i]);
60     }
61     if(k > 1)
62         printf(" %lld\n",b);
63     else
64         printf("\n");
65 }
66 int main()
67 {
68 //    freopen("C:/Users/14685/Desktop/stdin&&stdout/contest","r",stdin);
69     scanf("%d",&q);
70     while(q--)
71     {
72         scanf("%lld%lld%lld",&a,&b,&m);
73         Solve();
74     }
75     return 0;
76 }
View Code

 

bug:

  61~64最后输出语句,晚上重新敲的时候将其放到了for()里:

 1 printf("%d %lld",k,a);
 2 for(int i=2;i <= k;++i)
 3 {
 4     if(i == k)
 5     {
 6         printf(" %lld\n",b);
 7         return ;
 8     }
 9     ll d=val[k]-b;
10     ll x=min(m-1,d/(1ll*1<<(k-i-1)));
11 
12     val[i] -= x;
13     for(int j=i+1;j <= k;++j)
14         val[j] -= x,x += x;
15 
16     printf(" %lld",val[i]);
17 }

  一直是“Wrong answer on test 10”,debug了好一会,才发现,当 k = 1是,最后是有换行的;

  但是,放到for()里就缺少一个换行;

posted @ 2019-05-20 18:32  HHHyacinth  阅读(365)  评论(0编辑  收藏  举报