Codeforces Round #226 (Div. 2) 题解

C. Bear and Prime Numbers

    题意:有n(1e6)个数定义f(x)表示这n个数中是x的倍数的数的数目,有50000次询问,每次询问给出[L,R],需要计算出区间中所有质数的f函数和

    思路:用素数筛把素数都筛出来,然后做前缀和处理,每次O1回答

    代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e7 + 7;
bool pri[maxn];
int cnt[maxn];
int pre[maxn];

int main()
{
    int n;
    scanf("%d", &n);
    int maxe = 0;
    for(int i = 1; i <= n; i++) {
        int x;
        scanf("%d", &x);
        cnt[x] ++;
        maxe = max (maxe, x);
    }
    for(int i = 2; i <= maxe; i++) {
        if(pri[i])continue;
        for(int j = i; j <=maxe; j += i) {
            pre[i] += cnt[j];
            pri[j] = true;
        }
    }
    for(int i = 1; i <= maxe; i++) {
        pre[i] += pre[i - 1];
    }
    int m;
    scanf("%d", &m);
    while(m--) {
        int l, r;
        scanf("%d%d", &l, &r);
        r = min (r, maxe);
        if(l <= r) {
            printf("%d\n", pre[r] - pre[l - 1]);
        }
        else printf("0\n");
    }
    return 0;
}
View Code

D. Bear and Floodlight

    题意:平面上有n(20)个灯,每个灯在x,y坐标上,照射的夹角是x,现在问从[L,R]区间中,从L开始可以被灯光照射的地方,最长是多少

    思路:考虑装压,因为n只有20,定义dp[i]为i状态下的最优长度,每次计算出添加第j个灯后最长能到多长。

    代码:

#include <bits/stdc++.h>
using namespace std;

const double PI = acos(-1.0);
double x[25],y[25],a[25];
int n;
double l,r;
double dp[1<<20];
double calc(double xx,int i)
{
    double as = atan((r - x[i]) / y[i]);
    double qw = atan((xx - x[i]) / y[i]) + a[i];
    as = min(as,qw);
    return x[i] + tan(as) * y[i];
}

int main()
{
    scanf("%d%lf%lf", &n, &l, &r);
    r -= l;
    for(int i = 0; i < n; i++) {
        scanf("%lf%lf%lf", &x[i], &y[i], &a[i]);
        x[i] -= l;
        a[i] = a[i] / 180.0 * PI;
    }
    int len = 1 << n;
    for(int i = 0; i < len; i++) {
        for(int j = 0; j < n; j++) {
            if((i & (1 << j)) == 0) {
                dp[i ^ (1 << j)] = max(dp[i ^ (1 << j)], calc(dp[i], j));
            }
        }
    }
    printf("%.7f\n",dp[len - 1]);
    return 0;
}
View Code

E. Bear in the Field

    题意:有只熊,在一个n*n(1e9)的方格上,每个方格(x,y)有x+y个物品,每一秒每个格子的物品+1,现在有t秒,熊的初始速度是dx,dy每吃x个物品,dx和dy都会增加x的速度,假设熊当前在(x,y)那么下一秒的坐标是(x+dx%n + 1, y + dy%n + 1),

    思路:直接按照题目上的关系写出sx,sy,dx,dy,t,每相邻两秒之间的关系,然后构造出矩阵

    代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
LL MOD;
///使用前要先对r,c赋值
struct mat{
    long long a[30][30];
    int r,c;
    mat operator *(const mat &b)const{
        mat ret;
        for (int i=0;i<r;i++){
            for (int j=0;j<b.c;j++){
                ret.a[i][j]=0;
                for (int k=0;k<c;k++)
                    ret.a[i][j]+=a[i][k]*b.a[k][j],ret.a[i][j]%=MOD;
            }
        }
        ret.r=r;
        ret.c=b.c;
        return ret;
    }
    void init_unit(int x)
    {
        r=c=x;
        for(int i=0;i<r;i++){
            for(int j=0;j<c;j++){
                if(i==j)a[i][j]=1;
                else a[i][j]=0;
            }
        }
    }
}unit;
mat qmod(mat p,LL n){
    unit.init_unit(p.c);
    mat ans = unit;
    while(n) {
        if(n & 1)ans = p * ans;
        p = p * p;
        n >>= 1;
    }
    return ans;
}
LL n,sx,sy,dx,dy,t;

int main()
{
    scanf("%lld%lld%lld%lld%lld%lld", &n, &sx, &sy, &dx, &dy, &t);
    if(t == 0) {
        printf("%lld %lld\n", sx, sy);
        return 0;
    }
    MOD = n;
    mat A;
    A.r = A.c = 6;
    A.a[0][0] = 2; A.a[0][1] = 1; A.a[0][2] = 1; A.a[0][3] = 0; A.a[0][4] = 1; A.a[0][5] = 2;
    A.a[1][0] = 1; A.a[1][1] = 2; A.a[1][2] = 0; A.a[1][3] = 1; A.a[1][4] = 1; A.a[1][5] = 2;
    A.a[2][0] = 1; A.a[2][1] = 1; A.a[2][2] = 1; A.a[2][3] = 0; A.a[2][4] = 1; A.a[2][5] = 2;
    A.a[3][0] = 1; A.a[3][1] = 1; A.a[3][2] = 0; A.a[3][3] = 1; A.a[3][4] = 1; A.a[3][5] = 2;
    A.a[4][0] = 0; A.a[4][1] = 0; A.a[4][2] = 0; A.a[4][3] = 0; A.a[4][4] = 1; A.a[4][5] = 1;
    A.a[5][0] = 0; A.a[5][1] = 0; A.a[5][2] = 0; A.a[5][3] = 0; A.a[5][4] = 0; A.a[5][5] = 1;
    A = qmod(A,t);
    LL b[15];
    b[0]=sx - 1; b[1] = sy - 1; b[2] = dx; b[3] = dy; b[4] = 0; b[5] = 1;
    LL ansx = 0, ansy = 0;
    for(int i = 0; i < 6; i++)
        ansx=(ansx + A.a[0][i] * b[i] % MOD + MOD) % MOD;
    for(int i = 0; i < 6; i++)
        ansy=(ansy + A.a[1][i] * b[i] % MOD + MOD) % MOD;
    printf("%lld %lld\n",ansx + 1ll,ansy + 1ll);
    return 0;
}
View Code

 

posted @ 2019-02-26 23:07  啦啦啦天啦噜  阅读(199)  评论(0编辑  收藏  举报