【Codeforces Round #404 (Div. 2)】题解

A. Anton and Polyhedrons

直接统计+答案就可以了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 1000
#define LL long long
using namespace std;

char s[10000];

int main()
{
    int n;
    LL sum=0;
    scanf("%d",&n);
    while (n--) {
        scanf("%s",s);
        if (s[0]=='T') sum+=4;
        if (s[0]=='C') sum+=6;
        if (s[0]=='O') sum+=8;
        if (s[0]=='D') sum+=12;
        if (s[0]=='I') sum+=20;
    }
    printf("%I64d\n",sum);
    return 0;
}
View Code

 

B.Anton and Classes

算最大间隔。直接记录第一类第二类的最小的右端点和最大左端点。

然后答案就是第一类最大左端点-第二类最小右端点,第二类最大左端点-第一类最小右端点。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 1000
#define LL long long
#define inf 1000000000
#define rep(i,l,r) for(int i=l;i<=r;i++)
using namespace std;

int main()
{
    int n,m,max1=-inf,min1=inf,max2=-inf,min2=inf;
    scanf("%d",&n);
    rep(i,1,n) {
        int j,k;
        scanf("%d %d",&j,&k);
        max1=max(max1,j);
        min1=min(min1,k);
    }
    scanf("%d",&m);
    rep(i,1,m) {
        int j,k;
        scanf("%d %d",&j,&k);
        max2=max(max2,j);
        min2=min(min2,k);
    }
    int ans=0;
    ans=max(ans,max1-min2);
    ans=max(ans,max2-min1);
    printf("%d\n",ans);
    return 0;
}
View Code

 

c.Anton and Fairy Tale

首先分情况,如果n=1第一天就gg,n<=m,那第n才就gg,主要是n>=m的情况

首先前m天一定是满的,然后m+1天后每天减少等差数列颗,假设答案为x,则(1+(x-m))*(x-m)/2+x+1>=n,满足的最小的x+1就是答案,化简一下然后直接算就可以啦。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 1000
#define LL long long
#define inf 1000000000
#define rep(i,l,r) for(int i=l;i<=r;i++)
using namespace std;

int main()
{
    LL n,m;
    scanf("%I64d %I64d",&n,&m);
    if (!n) printf("0\n");
    else
    if (n==1) 
        printf("1\n");
    else
    if (n<=m) 
        printf("%I64d\n",n);
    else {
        LL sum=m;
        LL now=sqrt((n-m-1)*2)+1;
        while ((now+2)*(now-1)>=(n-m-1)*2) now--;
    //    printf("%I64d %I64d\n",now,now*(now*3));
        sum+=now+1;
        printf("%I64d\n",sum);
    }
    return 0;
}
View Code

 

d.Anton and School - 2

最不会的数学题,看了评论区的题解才知道怎么写……

范德蒙恒等式的证明

加个逆元就可以啦。

#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define dow(i,l,r) for(int i=r;i>=l;i--)
#define maxn 400100 
#define LL long long
#define mm 1000000007
using namespace std;

char s[maxn];
LL f1[maxn],f2[maxn],inv[maxn];

int main()
{
    scanf("%s",s);
    inv[1]=1;
    rep(i,2,maxn-1) inv[i]=mm-(mm/i)*inv[mm%i]%mm;
    f1[0]=f2[0]=f1[1]=f2[1]=1;
    rep(i,2,maxn-1) f1[i]=f1[i-1]*(LL)(i)%mm,f2[i]=f2[i-1]*inv[i]%mm;
    int len=strlen(s);
    int l=0,r=len-1;
    while (l<=r && s[l]==')') ++l;
    while (l<=r && s[r]=='(') --r;
    LL sum=0;
    int now1=0,now2=0;
    rep(i,l,r) if (s[i]==')') ++now2;
    rep(i,l,r) {
        if (s[i]=='(' && now2) sum=(sum+f1[now1+now2]*f2[now2-1]%mm*f2[now1+1]%mm)%mm,now1++;
        else now2--;
    }
    printf("%I64d\n",sum);
    return 0;
}
View Code

 

E.Anton and Permutation

题目是说每次交换两位置上的数,求当前逆序对的数量。

显然就是个树套树啦,不过太久没写就没写23333。树状数组套权值线段树。权值线段树用数组写开了20000000的大小才给过,看来要学习指针写法(p党的残念)。另外还得学会cdq分治的写法。

#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define dow(i,l,r) for(int i=r;i>=l;i--)
#define maxn 400100 
#define maxm 20001000 
#define LL long long
#define mm 1000000007
using namespace std;

int size[maxm],lson[maxm],rson[maxm],num[maxn],bit[maxn],n,total;

int addson() {return ++total;}
int lowbit(int x) {return x&(-x);}

void add(int &x,int l,int r,int y,int z)
{
    if (!x) x=addson();
    size[x]+=z;
    if (l==r) return;
    int mid=(l+r)>>1;
    if (y<=mid) add(lson[x],l,mid,y,z);
    else 
        add(rson[x],mid+1,r,y,z);
}

int ask(int x,int l,int r,int y)
{
    if (!x) return 0;
    if (l==r) return size[x];
    int mid=(l+r)>>1;
    if (y<=mid) return ask(lson[x],l,mid,y);
    else 
        return size[lson[x]]+ask(rson[x],mid+1,r,y);
}

LL bigask(int x,int y)
{
    LL now=0;
    while (x) {
        now+=ask(bit[x],1,n,y);
        x-=lowbit(x);
    }
    return now;
}

void bigadd(int x,int y,int z)
{
    while (x<=n) {
        add(bit[x],1,n,y,z);
        x+=lowbit(x);
    }
}

int main()
{
    int m;
    scanf("%d %d",&n,&m);
    LL sum=0;
    rep(i,1,n) bigadd(i,num[i]=i,1);
    while (m--) {
        int l,r;
        scanf("%d %d",&l,&r);
        if (l==r) {
            printf("%I64d\n",sum);
            continue;
        }
        if (l>r) swap(l,r);
        if (r-l>1) {
            sum-=2*(bigask(r-1,num[l])-bigask(l,num[l]));
            sum+=2*(bigask(r-1,num[r])-bigask(l,num[r]));
        }
        if (num[l]<num[r]) ++sum;else --sum;
        printf("%I64d\n",sum);
        bigadd(l,num[l],-1);
        bigadd(l,num[r],1);
        bigadd(r,num[r],-1);
        bigadd(r,num[l],1);
        swap(num[l],num[r]);
    }
    return 0;
}
View Code

 

posted @ 2017-03-16 18:16  Macaulish  阅读(295)  评论(0编辑  收藏  举报