2013ACM-ICPC杭州赛区全国邀请赛总结

A.Robot(hdu 4576)

思路:

  直接暴力之...现场赛的时候被这题坑成狗,怎么算复杂度也不够...求300MS的解法T^T

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include <map>
using namespace std;
double dp[2][210];
int main()
{
    int n,m,l,r,len;
    while(scanf("%d%d%d%d",&n,&m,&l,&r)!=EOF)
    {
        if(n+m+l+r==0) break;
        memset(dp,0,sizeof(dp));
        dp[1][1]=1;
        for(int i=0;i<m;i++)
        {
            scanf("%d",&len);
            int now=i&1;
            int pre=!now;
            for(int j=1;j<=n;j++)
            {
                int x=j+len;if(x>n) x-=n;
                int y=j-len; if(y<1) y+=n;
                dp[now][j]=dp[pre][x]+dp[pre][y];
                dp[now][j]/=2;
            }
        }
        double ret=0;
        int now=(m-1)&1;
        for(int i=l;i<=r;i++){
            ret+=dp[now][i];
        }
        printf("%.4lf\n",ret);
    }
    return 0;
}
hdu 4576

 

B.X-Boxes(hdu 4577)

思路:

  可以放的物品表示成a*1,a*2,a*4....所以,对于一个数n,假设要找k个数,则a有n/2^(k-1)种选择,比如第一个样例10/2=5,即a可以取1-5,但是里面有一些是重复的,比如选过1以后就不能选2,仔细观察后发现,如果只选奇数数字,就不会重复,所以a可以取1,3,5这3个数,但是这还漏掉了一些情况,以1开始的序列是1,2,4,8我们现在只用掉了1,2,所以剩下的部分也要算进去,所以最后的答案就是ans=can(n/2^(K-1))+can(n/2^(2k-1))+...直到2^(mk-1)>n,can(x)代表1-x中奇数的个数.但是这个式子直接算要超时...最后变成了下形式才过><

//没学过JAVA...代码各种捉急
import java.math.BigInteger;
import java.util.Scanner;

public class Main {    
    public static void main(String[] args){
        BigInteger MOD =BigInteger.valueOf(2);
        BigInteger ZEE = BigInteger.ZERO;
        BigInteger onn = BigInteger.ONE;
        int T;
        BigInteger len;
        int x;
        Scanner cin = new Scanner(System.in);
        T =cin.nextInt();
        for(int kk=0;kk<T;kk++){
            len=cin.nextBigInteger();
            x=cin.nextInt();
            BigInteger now=BigInteger.valueOf(2);
            BigInteger Inc = now.pow(x);
            now=Inc.divide(now);
            BigInteger ret =BigInteger.ZERO;
            BigInteger add=len.divide(now);
            BigInteger AC;
            BigInteger tt=add.mod(MOD);
            if(!tt.equals(ZEE))
            {
                AC=add.add(onn);
            }
            else AC=add;
            ret=ret.add(AC.divide(MOD));
            while(add.compareTo(ZEE)>0){
                add=add.divide(Inc);
                tt=add.mod(MOD);
                if(!tt.equals(ZEE))
                {
                    AC=add.add(onn);
                }
                else AC=add;
                ret=ret.add(AC.divide(MOD));
            }
            System.out.println(ret);
        }    
    }
}
hdu 4577

 

C.Transformation(hdu 4578)

思路:

  其实这题的难点就是延迟标记...如果和一般的一样的话就是最裸的区间更新+区间查询,我是把每个标记都存在队列里..没想到居然没有超时T^T,其实这个方法应该算是卡过的,其实可以只记录add,sum,cover就可以了,心情好的时候再重写-, -

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define mod 10007
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

int sum1[401000],sum2[401000],sum3[401000],ret;
queue<int>q[401000];
void pushup(int rt){
    sum1[rt]=(sum1[rt<<1]+sum1[rt<<1|1]) %mod;
    sum2[rt]=(sum2[rt<<1]+sum2[rt<<1|1]) %mod;
    sum3[rt]=(sum3[rt<<1]+sum3[rt<<1|1]) %mod;
}
void change1(int rt,int len,int c){
    sum3[rt]=(sum3[rt]+c*c%mod*c%mod*len%mod+3*c*sum2[rt]%mod+3*c*c%mod*sum1[rt]%mod)%mod;
    sum2[rt]=(2*c%mod*sum1[rt]%mod+c*c%mod*len%mod+sum2[rt])%mod;
    sum1[rt]=(sum1[rt]+len*c)%mod;
}
void change2(int rt,int len,int c){
    sum3[rt]=c*c%mod*c%mod*sum3[rt]%mod;
    sum2[rt]=sum2[rt]*c%mod*c%mod;
    sum1[rt]=sum1[rt]*c%mod;
}
void change3(int rt,int len,int c){
    sum3[rt]=len*c%mod*c%mod*c%mod;
    sum2[rt]=len*c%mod*c%mod;
    sum1[rt]=len*c%mod;
}
void pushdown(int rt,int len){
    int ls=rt<<1,rs=rt<<1|1;
    int lenr=len/2;
    int lenl=len-lenr;
    while(!q[rt].empty()){
        int now=q[rt].front();
        q[rt].pop();
        if(now>=300000){
            while(!q[ls].empty()) q[ls].pop();
            while(!q[rs].empty()) q[rs].pop();
        }
        q[ls].push(now);
        q[rs].push(now);
        if(now>=300000){
            change3(ls,lenl,now-300000);
            change3(rs,lenr,now-300000);
        }
        else if(now>=200000){
            change2(ls,lenl,now-200000);
            change2(rs,lenr,now-200000);
        }
        else if(now>=100000){
            change1(ls,lenl,now-100000);
            change1(rs,lenr,now-100000);
        }
    }
}
void update(int op,int L,int R,int c,int l,int r,int rt)
{
    int len=r-l+1;
    if(L<=l&&R>=r){
        if(op==1){
            change1(rt,len,c);
            q[rt].push(c+100000);
        }
        else if(op==2){
            change2(rt,len,c);
            q[rt].push(c+200000);
        }
        else if(op==3){
            change3(rt,len,c);
            q[rt].push(c+300000);
        }
        return;
    }
    pushdown(rt,len);
    int m=(l+r)>>1;
    if(L<=m) update(op,L,R,c,lson);
    if(R>m) update(op,L,R,c,rson);
    pushup(rt);
}
void query(int L,int R,int p,int l,int r,int rt){
    if(L<=l&&R>=r){
        if(p==1) ret+=sum1[rt];
        if(p==2) ret+=sum2[rt];
        if(p==3) ret+=sum3[rt];
        if(ret>=mod) ret%=mod;
        return;
    }
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(L<=m) query(L,R,p,lson);
    if(R>m) query(L,R,p,rson);
    pushup(rt);
}
int main(){
    int n,m,op,x,y,p;
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0&&m==0) break;
        memset(sum1,0,sizeof(sum1));
        memset(sum2,0,sizeof(sum2));
        memset(sum3,0,sizeof(sum3));
        for(int i=1;i<=4*n;i++){
            while(!q[i].empty()) q[i].pop();
        }
        while(m--)
        {
            scanf("%d%d%d%d",&op,&x,&y,&p);
            if(op==4){
                ret=0;
                query(x,y,p,1,n,1);
                printf("%d\n",ret);
            }
            else
                update(op,x,y,p,1,n,1);
        }
    }
    return 0;
}
hdu 4578

 

I.Building bridges(hdu 4584)

思路:

  暴力枚举一下...不解释了

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3fffffff
char map[50][50];
int main()
{
    int m,n,ansx1,ansy1,ansx2,ansy2;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0) break;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",map[i]+1);
        }
        int min=INF;
        for(int x1=1;x1<=n;x1++)
            for(int y1=1;y1<=m;y1++)
                for(int x2=1;x2<=n;x2++)
                    for(int y2=1;y2<=m;y2++)
                        if(map[x1][y1]=='H'&&map[x2][y2]=='C')
                        {
                            int dis=abs(x2-x1)+abs(y2-y1);
                            if(dis<min){
                                min=dis;
                                ansx1=x1;
                                ansx2=x2;
                                ansy1=y1;
                                ansy2=y2;
                            }
                        }
        printf("%d %d %d %d\n",ansx1-1,ansy1-1,ansx2-1,ansy2-1);
    }
    return 0;
}
hdu 4584

 

J.Shaolin(hdu 4585)

思路:

  原来不太会用STL里的set....今天看这题的时候又一种感觉...出题人不就是让用set的么- -

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include <map>
#include <set>
using namespace std;
struct Point{
    int id,x;
    bool operator <(const Point & tem)const{
        return x<tem.x;
    }
};
set<Point>q;
int main()
{
    int n,Id,num;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0) break;
        Point hehe;
        hehe.id=1;
        hehe.x=1000000000;
        q.clear();
        q.insert(hehe);
        for(int i=2;i<=n+1;i++)
        {
            scanf("%d%d",&Id,&num);
            hehe.id=Id;
            hehe.x=num;
            set<Point>::iterator now =q.lower_bound(hehe),tem1,tem2;
            tem1=tem2=now;
            if(tem1!=q.begin())tem1--;
            int va1=(num-tem1->x),va2=(tem2->x-num);
            if(va2<va1)
                printf("%d %d\n",Id,tem2->id);
            else
                printf("%d %d\n",Id,tem1->id);
            q.insert(hehe);
        }
    }
    return 0;
}
hdu 4585


 

  

posted @ 2013-08-10 21:09  破晓べ  阅读(444)  评论(0编辑  收藏  举报