codeforces--280--

其实本场 很水 = =B C都犯了sb错误挂了..

B挂在 自己代码里没有考虑N=1的情况

C挂在 在Int向LL进行强制转换的时候 先溢出了  以后应该这样写 1LL * x * y 或者直接将x y定义为LL

D E porker帮忙= =解释 明天给 睡觉了 3点半了 我擦

B

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int n , l;
 6 const int size = 1010;
 7 int a[size];
 8 
 9 double solve( )
10 {
11     double ans = max( a[0] , l-a[n-1] );
12     for( int i = 1 ; i<n ; i++ )
13     {
14         ans = max( ans , (a[i]-a[i-1])*1.0/2 );
15     }
16     return ans;
17 }
18 
19 int main()
20 {
21     double ans;
22     while( ~scanf("%d %d",&n,&l ) )
23     {
24         for( int i = 0 ; i<n ; i++ )
25         {
26             scanf( "%d",&a[i] );
27         }
28         sort( a , a+n );
29         ans = solve( );
30         printf( "%.10lf
",ans );
31     }
32     return 0;
33 }
View Code

C

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 typedef __int64 LL;
 6 const int size = 100010;
 7 struct data
 8 {
 9     int a , b;
10 }node[size];
11 
12 bool cmp( const data p , const data q )
13 {
14     return p.b < q.b;
15 }
16 
17 int main()
18 {
19     int r;
20     LL ans , sum , temp , n , avg;
21     while( ~scanf("%I64d %d %I64d",&n,&r,&avg) )
22     {
23          sum = 0;
24          ans = 0;
25         for( int i = 0 ; i<n ; i++ )
26         {
27             scanf( "%d %d",&node[i].a,&node[i].b );
28             sum += node[i].a;
29         }
30         if( sum >= avg*n )
31         {
32             printf( "0
" );
33         }
34         else
35         {
36             sum = avg*n - sum;
37             sort( node , node+n , cmp );
38             for( int i = 0 ; i<n ; i++ )
39             {
40                 if( sum<=0 )
41                     break;
42                 if( r-node[i].a > 0 )
43                 {
44                     temp = min( (LL)r-node[i].a , sum );
45                     sum -= temp;
46                     ans += (LL)(temp * node[i].b);
47                 }
48             }
49             printf( "%I64d
",ans );
50         }
51     }
52     return 0;
53 }
View Code

D

就是说A射完X枪的时候 B射完了Y枪 怪物有k滴血 我们要判断当怪物血为0的那一刻是被谁打死的 A or B or both<就是说本来还有2滴血 2个人正好在这一时刻同时打枪 那么正好变成了血量为0 , 就是说Both>

其实 你可以发现A射完x枪 B射完y枪 其实是等价于A射完 x/gcd(x,y)  B射完 y/gcd(x,y)的。  这可以帮我们很大的减小数据规模 不然我们都可以直接暴力模拟了

不仅仅是减小了数据规模 而且我们保证了在A没有射出第X枪之前 A B不可能在同一时刻一起打枪

and k % (x+y)  < x是x/=gcd(x,y) y 同理 > 与去击杀K滴血的怪是一样的 这也是个很重要的减小规模 因为我们也相当与去除 k/(x+y)次轮的射击 因为每次都是相同的

所以 我现在就可以枚举计算了 枚举的变量是 第几枪 从 1->x+y-1之间

if判断就是说A与B谁先射这第I枪  A/x < B/y  因为整数除法会取整 所以需要移项用乘法进行计算 即 A*y < B*x   result就是记录第 i 枪是谁射的.

我想 最重要的一步操作是 能否想到gcd处理。

= =

本题也可以通过二分时间来做。

 1 #include <iostream>
 2 using namespace std;
 3 
 4 long long gcd(long long a, long long b) {
 5     while (b) {
 6         long long c = a % b;
 7         a = b;
 8         b = c;
 9     }
10     return a;
11 }
12 
13 bool result[2001000];
14 
15 int main() {
16     int n;
17     long long x, y;
18     cin >> n >> x >> y;
19     long long g = gcd(x, y);
20     x /= g;
21     y /= g;
22     long long sum = x + y;
23     int shotsA = 0, shotsB = 0;
24     for (int i = 1; i < sum; i++) {
25         int newshotA = shotsA + 1;
26         int newshotB = shotsB + 1;
27         if (newshotA * y < newshotB * x) {
28             shotsA = newshotA;
29             result[i] = true;
30         }
31         else {
32             shotsB = newshotB;
33             result[i] = false;
34         }
35     }
36     while (n--) {
37         long long a;
38         cin >> a;
39         a = a % sum;
40         if (a == 0 || a == sum - 1) {
41             cout << "Both" << endl;
42         }
43         else if (result[a]) {
44             cout << "Vanya" << endl;
45         }
46         else {
47             cout << "Vova" << endl;
48         }
49     }
50 }
View Code

E

E我讲不大清楚 = = 有点乱。

首先你要得出一个结论:任何一个点  走n步 都将回到起点  因为 ( x + n*dx ) % n == ( y + n*dy ) % n == 0

同时 又有一个数论中的知识点 在 gcd( a , c ) = 1 的情况下    a * b % c  (0<=b<=c-1)的值将会是[0,c-1]区间的任意一个值 可以这样说 得到的将是[0,c-1]一共c个数的任意序列  那么因为 题目告诉了我们 gcd( dx , n ) = gcd( dy , n ) = 1 所以那就可以得到我们从任意一点走n步回到起点得到的这条回路 都是[0,n-1]的独一无二的坐标 就是说没有2个拥有相同的横坐标 或者 纵坐标.  那么这个回路中的任意一点都是属于这个环的 我们想个方法来区分这么多不同的环。 我们通过一个 特征值来区分。

因为环上的每个点 横 纵坐标不相同   我可以取纵坐标Y=0 横坐标x为特征值 来对应不同的环。

其实就是说 对于每个点 在自身所在的环内 查找出一个点 y = 0 x为特征值来用counts数组记录

那就是说 y + k*dy = 0 (mod)n 就表示<x,y>走k步可以走到纵坐标是0的点  移项处理就是  k * dy = (n-y)mod(n)

我们可以预处理将所有 k * dy都计算出来 将k计录在 table[n-y]中   这样我每次通过 y 找k的时候 都可以在table[n-y]里面找

打表O(n) 查询O(1)  

amazing . 

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 int table[1000010];
 6 int counts[1000010];
 7 
 8 int main() {
 9     int n, m, dx, dy;
10     cin >> n >> m >> dx >> dy;
11     int y = 0;
12     for (int i = 0; i < n; i++) {
13         table[n - y] = i;
14         y += dy;
15         y %= n;
16     }
17     table[0] = table[n];
18     memset(counts, 0, sizeof(counts));
19     int result = 0;
20     long long locx, locy;
21     while (m--) {
22         long long x, y;
23         cin >> x >> y;
24         long long k = table[y];
25         long long newx = (x + k * dx) % n;
26         counts[newx]++;
27         if (counts[newx] > result) {
28             result = counts[newx];
29             locx = x;
30             locy = y;
31         }
32     }
33     cout << locx << " " << locy << endl;
34 }
View Code

today:

  where'd you go

原文地址:https://www.cnblogs.com/radical/p/4136439.html