google亚太在线笔试2017-RoundB

来源:互联网 发布:ubuntu rc.local不存在 编辑:程序博客网 时间:2024/05/01 16:41

google亚太在线笔试2017-RoundB

Problem A

题意:

定义’(‘和’)’所组成的平衡串为:
(1).空串,or
(2).(S),S为平衡串,or
(3).S1S2,其中S1和S2均为平衡串
接下来给你由L个’(‘和R个’)’,求解怎样排列,可以使所得的字符串有最多的非空平衡子串,输出此时的平衡子串的数目
数据量:
0L105.
0R105.
1L+R105.

分析:

易证明:另n = min(L, R),可以得到的最多非空平衡子串数目为n*(n+1)/2;即排列成()()()….这样的形式

代码:

//#include <iostream>#include <fstream>using namespace std;#define mini(a, b) ((a)<(b)?(a):(b))long long T, L, R;ifstream cin("A-large.in", ios::in);ofstream cout("A-large.out", ios::out);int main(){    cin>>T;    int Case = 0;    while(T--){        Case ++;        cin>>L>>R;        long long num = mini(L, R);        long long maximum = (num+1)*(num)/2;        cout<<"Case #"<<Case<<": "<<maximum<<endl;    }    return 0;}

Problem B: Sherlock and Watson Gym Secrets

题意:

给定A, B, N, K,求存在多少对的(i, j)(其中1<=i, j<=N且i != j),使得K|(iA+jB),输出mod 109+7的结果
数据量:
0A106.
0B106.
1K100000.
1N1018.

分析:

(iA+jB)modK=(iAmodK+jBmodK)
通过这个可以将N缩小到K的范围
剩下只需要考虑的是i != j这个条件,将其减去就可以

代码:

//#include <iostream>#include <fstream>using namespace std;#define mod 1000000007long long T, A, B, N, K;long long a[100000], b[100000];ifstream cin("B-large-practice.in", ios::in);ofstream cout("B-large-practice.out", ios::out);long long power(long long a, long long x){    long long res = 1;    for(long long k = (1<<30);k >= 1;k >>= 1){        res = (res*res)%K;        if((x&k) != 0) res = (res*a)%K;    }    return res;}int main(){    cin>>T;    int Case = 0;    while(T --){        Case ++;        cin>>A>>B>>N>>K;        long long num = 0, iA, jB;        for(int i = 0;i < 100000;i ++){            a[i] = 0;            b[i] = 0;        }        long long m = (N/K)%mod;        long long n = N%K;        for(int i = 1;i <= n;i ++){            iA = power(i, A);            jB = power(i, B);            if((iA + jB)%K == 0){                num = (num + ((m+1)*b[(K-iA)%K])%mod)%mod;                num = (num + ((m+1)*a[(K-jB)%K])%mod)%mod;                num = (num + ((m+1)*m)%mod)%mod;            }            else{                num = (num + ((m+1)*b[(K-iA)%K])%mod)%mod;                num = (num + ((m+1)*a[(K-jB)%K])%mod)%mod;            }            a[iA] = (a[iA] + m + 1)%mod;            b[jB] = (b[jB] + m + 1)%mod;        }        if(m > 0){        for(int i = n + 1;i <= K;i ++){            iA = power(i, A);            jB = power(i, B);            if((iA + jB)%K == 0){                num = (num + (m*b[(K-iA)%K])%mod)%mod;                num = (num + (m*a[(K-jB)%K])%mod)%mod;                num = (num + (m*(m-1))%mod)%mod;            }            else{                num = (num + (m*b[(K-iA)%K])%mod)%mod;                num = (num + (m*a[(K-jB)%K])%mod)%mod;            }            a[iA] = (a[iA] + m)%mod;            b[jB] = (b[jB] + m)%mod;        }        }        cout<<"Case #"<<Case<<": "<<num<<endl;    }    return 0;}

Problem C: Watson and Intervals

题意:

定义区间[L, R]的面积如下:
R - L + 1,即区间所覆盖的整数数目
给你N个闭合区间,求删去哪个区间后,这N个区间所覆盖的面积之和最小,最小为多少(面积之和为所有区间所覆盖的不同整数的数目之和)

分析:

sweep line策略

代码:

#include <fstream>#include <algorithm>using namespace std;#define MIN(a,b) ((a)<(b)?(a):(b))#define MAX(a,b) ((a)>(b)?(a):(b))#define maxm 500000enum {INC, DEC};struct Interval{    int L;    int R;    int coverarea;}interval[maxm];struct Label{    int point;    int sign;    int covertime;    bool operator < (const Label a) const{        return point < a.point;    }}label[2*maxm];int cover[2*maxm];long long T, L1, R1, A, B, C1, C2, M, n;ifstream cin("C-large-practice.in", ios::in);ofstream cout("C-large-practice.out", ios::out);void init(){    interval[0].L = L1;    interval[0].R = R1;    for(int i = 1;i < n;i ++){        interval[i].L = (A*interval[i-1].L + B*interval[i-1].R + C1)%M;        interval[i].R = (A*interval[i-1].R + B*interval[i-1].L + C2)%M;    }    long long x, y;    for(int i = 0;i < n;i ++){        x = interval[i].L;        y = interval[i].R;        interval[i].L = MIN(x, y);        interval[i].R = MAX(x, y);        label[2*i].point = interval[i].L;        label[2*i].sign  = INC;        label[2*i+1].point = interval[i].R + 1;        label[2*i+1].sign = DEC;    }    sort(label, label + 2*n);}int binary_search(int begins, int ends, int key){    if(begins > ends) return begins;    else{        int r = (begins + ends)/2;        if(label[r].point == key) return r;        else if(label[r].point < key) return binary_search(r + 1, ends, key);        else return binary_search(begins, r - 1, key);    }}int solve(){    int covertime = 0;    for(int i = 0;i < 2*n;i ++){        if(label[i].sign == INC)            covertime ++;        else            covertime --;        label[i].covertime = covertime;    }    cover[0] = 0;    for(int i = 1;i < 2*n;i ++){        cover[i] = cover[i-1];        if(label[i-1].covertime == 1)            cover[i] += (label[i].point - label[i-1].point);    }    int labelL, labelR;    for(int i = 0;i < n;i ++){        labelL = binary_search(0, 2*n-1, interval[i].L);        labelR = binary_search(0, 2*n-1, interval[i].R + 1);        interval[i].coverarea = cover[labelR] - cover[labelL];    }    int max_coverarea = 0;    for(int i = 0;i < n;i ++)        if(interval[i].coverarea > max_coverarea)            max_coverarea = interval[i].coverarea;    int sum_coverarea = 0;    for(int i = 0;i < 2*n-1;i ++)        if(label[i].covertime > 0)            sum_coverarea += (label[i+1].point - label[i].point);    sum_coverarea -= max_coverarea;    return sum_coverarea;}int main(){    cin>>T;    int Case = 0;    while(T --){        Case ++;        cin>>n>>L1>>R1>>A>>B>>C1>>C2>>M;        init();        cout<<"Case #"<<Case<<": "<<solve()<<endl;    }    return 0;}
0 0
原创粉丝点击