Codeforces Round #226 (Div. 2)

A. Bear and Raspberry

题意:找到相邻差值最大的差值。

分析:水题,直接做。

Codeforces Round #226 (Div. 2)
/****************************************
* File Name: 226a.cpp
* Author: sky0917
* Created Time: 2014年01月24日 23:33:21
****************************************/
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100005;

int v[maxn];
int main(){
    int n, m;
    int a, b, c;
    int x;
    while (scanf("%d %d",&n,&x)!=EOF){
        int ma = 0;
        int re = 0;
        for (int i=0; i<n; i++){
            scanf("%d",&v[i]);
        }       
        for (int i=1; i<n; i++){
            if (v[i-1] - v[i] > re){
                re = v[i-1] - v[i];
            }
        }
        printf("%d\n",max(0, re-x));
    }   
    return 0;
}
View Code

 

B. Bear and Strings

题意:给出一个字符串 s (1?≤?|s|?≤?5000),问这个字符串中有多少个子串中含有至少一个“bear”单词。

分析:遍历一遍字符串,维护一个cnt,表示枚举的子串的开头位置的最左端

             例如: acbeartbear

             第一次发现 bear 之后,假如b的位置为 i ,那么:res += (i-cnt+1)*(len-i-3)

             然后 cnt = i+1,这样就不会出现重复枚举的情况了。

Codeforces Round #226 (Div. 2)
/****************************************
* File Name: 226b.cpp
* Author: sky0917
* Created Time: 2014年01月24日 23:33:26
****************************************/
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 5005;

char s[maxn];

int main(){
    while (scanf("%s",&s)!=EOF){
        long long res = 0;
        long long len = strlen(s);
        long long cnt = 0;
        for (long long i=0; i<len-3; i++){
            if (s[i]==b && s[i+1]==e && s[i+2]==a && s[i+3]==r){
                long long l = i-cnt+1;
                long long r = len - i - 3;
                res += l * r;
                cnt = i+1;
            }   
        }
        printf("%I64d\n",res);
    }
    return 0;
}
View Code

 

C. Bear and Prime Numbers

题意:  有 n (1?≤?n?≤?106) 个数,x1,?x2,?...,?xn (2?≤?xi?≤?107). 还有 m (1?≤?m?≤?50000) 个询问,每个询问为:l,r

             表示要求出[l, r]区间中所有的质数 p 的 f (p) 之和,f (p) 表示n个数中能被p整除的数的个数。

分析: 可以先打一个sqrt(1E7)范围的素数表,然后遍历一遍 n 个数,对每个数分解质因数,并用标记

              数组标记,例如某个数有质因子 p,那么vis[p]++, 最后处理出一个sum[i] 数组,sum[i]表示vis[i]

              数组中前 i 项的和,对于询问 l, r 输出 sum[r] - sum[l-1] 即可。

 

Codeforces Round #226 (Div. 2)
/****************************************
* File Name: 226c.cpp
* Author: sky0917
* Created Time: 2014年01月24日 23:33:45
****************************************/
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1000005;

int ma;
int v[maxn*10];

int vis[10003];
int p[10004];
int tp;
void print(){
    tp = 0;
    for (int i=2; i<10000; i++){
        if (!vis[i]){
            p[tp++] = i;
            for (int j=i*2; j<10000; j+=i){
                vis[j] = 1;
            }   
        }
    }   
}   
void cal(int x){
    for (int i=0; p[i]*p[i] <= x && i<tp; i++){
        if (x % p[i] == 0){
            v[p[i]]++;
            while (x % p[i] == 0){
                x /= p[i];          
            }   
        }   
    }
    if (x != 1){
        v[x]++;
    }
}

int val[maxn];
int sum[maxn*10];
int main(){
    int n, m;
    int va;
    print();    
    while (scanf("%d",&n)!=EOF){
        ma = 0;
        for (int i=0; i<n; i++){
            scanf("%d",&val[i]);
            if (val[i] > ma)
                ma = val[i];
        }
        for (int i=0; i<n; i++){
            cal(val[i]);    
        }   
        
        for (int i=1; i<=ma; i++){
            sum[i] = sum[i-1] + v[i];
        }
        scanf("%d",&m);
        int l, r;
        while (m--){
            scanf("%d %d",&l, &r);
            if (l > ma){
                printf("0\n");continue;
            }
            r = min(ma, r);
            printf("%d\n",sum[r]-sum[l-1]); 
        }
    }   
    return 0;
}
View Code

 

 

D. Bear and Floodlight

题意: 有 n(n<20) 个灯,每个灯有一个自己可以照亮的角度di,现在某个人要从(l,0) 走到(r,0)的位置,需要一开始调整

         好灯的角度,使得这个人一路上都可以被灯照到,这个人走的路线是一条线段,问这个最多能走多远,当然最多不会超过

         r 位置。

分析:状态压缩DP+向量旋转。

        dp[st] 表示在 s 状态下,最远走的位置,s中..001010.. 1表示用了那个灯,0表示没用,然后枚举没有用的灯,让其

        一开始的向量为(dp[st]-x0, -y0) 逆时针转 di 度得到新的向量,求出其和x轴的交点(x1,0) 

         那么dp[st|(1<<j)] = max(dp[st|(1<<j)], x1)

         最后输出dp[st] 和 r 的最小值 再减去 l 就好。

         注意一个情况,就是旋转过程中可能出现与x轴没有交点的情况,这个时候把 dp[st|(1<<j)] = r 就可以了。

Codeforces Round #226 (Div. 2)
/****************************************
* File Name: 226d.cpp
* Author: sky0917
* Created Time: 2014年01月25日  0:50:46
****************************************/
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const double p = acos(-1.0);
double dp[1<<21];
int n;
double l, r;
struct node{
    double x, y, di;
}q[22];

int main(){
    
    while (scanf("%d %lf %lf",&n,&l,&r)!=EOF){
    
        for (int i=0; i<n; i++){
            scanf("%lf %lf %lf",&q[i].x,&q[i].y,&q[i].di);
        }

        int st = 1<<n;
        for (int i=0; i<st; i++){
            dp[i] = -9999999.0;
        }   
        dp[0] = l;
        for (int i=0; i<st; i++){
            for (int j=0; j<n; j++){
                if (((1<<j)&i) == 0){
                    int sta = i | (1<<j);   
                    double x = dp[i] - q[j].x;
                    double y = -q[j].y;
                    double a = x*cos(p*q[j].di/180)-y*sin(p*q[j].di/180);
                    double b = x*sin(p*q[j].di/180)+y*cos(p*q[j].di/180);
                    if (b >= 0){
                        dp[sta] = r;
                        continue;
                    }
                    double tmp = y*a/b+q[j].x;
                    dp[sta] = max(dp[sta], tmp);
                }
            }
        }
        printf("%.10lf\n",min(r, dp[st-1])-l);
    }   
    return 0;
}
View Code

Codeforces Round #226 (Div. 2)

上一篇:vim实用笔记


下一篇:ubuntu自定义服务模板