Codeforces Round #138 (Div. 2)

来源:互联网 发布:淘宝手机端搭配套餐 编辑:程序博客网 时间:2024/06/01 07:41

第一次Codeforces.做出三题,但是第二题,有个细节没考虑到。Rating:1500+151=1651,于是下次继续Div2吧。>_<!

 

 

A:

题目给出平行六面体的连接一个顶点的三个面的面积,输出这个12条棱的和。

只要枚举下一条边,求出另外的两条边就行了。

#include<cstdio>#include<iostream>#include<cstdlib>using namespace std;int a,b,c;bool work(int a,int b,int c){    int j,k;    for (int i = 1;i*i<=a;++i)    if (a % i == 0)    {        j = a / i;        if (b % j == 0)        {            k = b / j;            if (c == i * k )            {                cout << (i+j+k)*4 << endl;                return 1;            }        }    }    return 0;}int main(){    cin >> a >> b >> c;    if (work(a,b,c) || work(a,c,b) || work(b,a,c)        || work(b,c,a) || work(c,a,b) || work(c,b,a) )        {            return 0;        }    return 0;}


B:

给数组a,包含n个元素,人物是找到inclusion segment[l,r].使得,al    al+1 … ar,包含了正好k个不同的数字。Definclusion : if there is no segment [x, y]satisfying the property and less thenm inlength, such that 1 ≤ l ≤ x ≤ y ≤ r ≤ n然后r-l不一定要最小。

直接上代码:

 

#include<iostream>#include<cstdio>using namespace std;int n,k,d,cnt,left = 1;;int a[200000];int flag[200000];int initial = -1;int main(){    cin >> n >> k;    cnt = 0;    for (int i = 1;i<=100000;++i) flag[i] == 0;    for (int i = 0;i<n;++i)    {        scanf("%d",&d);        a[i] = d;        if (flag[d] == 0)        {            ++cnt;            ++flag[d];            if (cnt == k)            {                int l = 0;                while (l+1<i && flag[a[l]]>1) { --flag[a[l]];++l; }                printf("%d %d\n",l+1,i+1);                return 0;            }        }else ++flag[d];    }    printf("-1 -1\n");    return 0;}

C:

定义括号字符串为包含[] & () 的字符串。然后题目费劲地想表达的是找到一个最大的满足匹配的子串,使得”[”的数目最多,并输出这个子串。

用栈来做,遇到左括号压栈,遇到右括号弹出。然后用个计数器,累加,每当出现不匹配的情况,就清空计数器,很容易顺便求出最大值和这个子串。

但是不能处理这种情况([]([]

为了处理这种情况,我把[]的这个计数器统计到(只有当有右括号匹配(时,[]才会被统计。

实现起来只是添加了一个和栈内元素对应的数组来记录计数。

 

#include<iostream>#include<cstdio>#include<string>using namespace std;string s;int stack[200000];int value[200000];int n;int transfer(char c){    if (c == '(') return 2;    if (c == '[') return 1;    if (c == ']') return -1;    if (c == ')') return -2;}int top  = 0;int bj = 0;int main(){    cin >> s;    n = s.size();    int now = 0,ans = 0;    for (int i = 0;i<s.size();++i)    {        if (transfer(s[i]) >0 )        {            stack[top] = transfer((s[i]));            value[top] = now;            now = 0;            ++top;        } else{            if (top == 0 || transfer(s[i]) + stack[top-1] != 0)            {                top = 0;                now = 0;                continue;            }            --top;                now += value[top];            if (transfer(s[i]) == -1) ++now;            if (now > ans )            {                ans = now;                bj = i;            }        }    }    cout << ans << endl;    int rs = 0,ls = 0,lc = 0,rc = 0;    if (ans != 0)    {        int tp = bj;        while (tp>=0)        {            if (s[tp] == ']') ++ rs;            if (s[tp] == '[') ++ ls;            if (s[tp] == '(') ++ lc;            if (s[tp] == ')') ++ rc;            if (ls == ans && rs == ans && lc == rc)            {                cout << string(s,tp,bj-tp+1) << endl;                return 0;            }            --tp;        }    }    return 0;}

D:

得到两个字串ST,考虑一类子串X=sk1sk2…skn.满足k1<k2<…<kn.

判断是否对于所有的I, X=sk1sk2…skn,X=T 并且 Kj=i.

计算出Left[i] i=0..T.size(),表示S中的所有X中能够匹配T[i]的极左。

同理计算出Right[i]表示能够匹配T[i]的极右。然后题目就变成了一些线段能否覆盖所有线段。

可以用类似括号匹配的方法来做

#include<iostream>#include<cstdio>#include<algorithm>#include<string>using namespace std;const int N = 200005;string S,T;int occ[256];int markL[N],markR[N];int main(){    cin >> S >> T;    int l,r;    r = 0;    for (l = 0;l<S.size();++l)    {        if (r<T.size() && S[l] == T[r]) markL[l]++, ++r;    }    if (r<T.size())    {        puts("No");        return 0;    }    r = T.size()-1;    for ( l = S.size()-1;l>=0;--l)    {        if (r>=0 && S[l] == T[r]) markR[l]-- , --r;    }//    for (int i = 0;i<S.size();++i) cout << markL[i] << " " << markR[i] << endl;    for (int i = 0;i<S.size();++i)    {        occ[S[i]] += markL[i];        if (occ[S[i]] == 0)        {            puts("No");            return 0;        }          occ[S[i]] += markR[i];    }    puts("Yes");    return 0;}
 

E:

给出一个数组n元数组a。我们队数组a进行k次操作。操作定义如下。

1、

2、把s赋给a。

输出k次操作后的数组a。

因为(1 ≤ n ≤ 2000,0 ≤ k ≤ 109)所以不能用矩阵乘法(n太大了).

推出公式:

    要推出这个公式也不难,先不要考虑a,然后观察操作后Si的值(这个值有aj的系数组成).


#include<iostream>#include<cstdio>using namespace std;#define LL long longconst LL MOD = 1000000007;//const LL MOD = 7;LL myDiv(int x){    LL res = 1;    LL tmp = x;    int y = MOD-2;    while (y>0)    {        if (y % 2 == 1)        {            res *= tmp;            res %= MOD;        }        y/= 2;        tmp *= tmp;        tmp %= MOD;    }    return res;}LL getC(int n,int k){    LL res = 1;    for (int i = 1;i<=k;++i)    {        res = res * (n-i+1);        res %=  MOD;        res = res * myDiv(i);        res %= MOD;    }    return res;}int n,k;LL ar[2005],Ans[2005];int C[2005];int main(){    cin >> n >> k ;    for (int i = 0;i<n;++i)        scanf("%d",&ar[i]);    if (k==0)    {        for (int i = 0;i<n;++i) Ans[i] = ar[i];    } else {        for (int i = 0;i<=n;++i)        {            C[i] = getC(k-1+i,i);      //     cout << i << " " << C[i] << endl;        }        for (int i = 0;i<n;++i)        {            Ans[i] = 0;            for (int j = 0;j<=i;++j)            {                Ans[i] += ar[j] * C[i-j];//                cout << C[i-j] << endl;                Ans[i] %= MOD;            }        //    printf("\n");        }    }    for (int i = 0;i<n-1;++i)    {        printf("%d ",Ans[i]);    }    printf("%d\n",Ans[n-1]);    return 0;}



原创粉丝点击