2013ACM-ICPC杭州赛区全国邀请赛总结
思路:
直接暴力之...现场赛的时候被这题坑成狗,怎么算复杂度也不够...求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; }
思路:
可以放的物品表示成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); } } }
思路:
其实这题的难点就是延迟标记...如果和一般的一样的话就是最裸的区间更新+区间查询,我是把每个标记都存在队列里..没想到居然没有超时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; }
思路:
暴力枚举一下...不解释了
#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; }
思路:
原来不太会用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; }