17.9.29

  • 上午
    • 模拟考试
      • Prob 1(AC).水题。
      • Prob 2(WA).类似紫书P269例题9-3(旅行),多了一个条件: 两条路必须分别经个给定的点

        一个经典的DP转移 dp[i][j]—>dp[max(i,j)+1][j]和dp[i][max(i,j)+1]

        此转移用于两条路跑完所有点。

        对于新添加的条件,只需在转移时让一个点只出现在状态的第一维,另一个点只出现在状态的第二维上午 Prob.2 

        代码:

        #include<cmath>
        #include<cstdio>
        #include<cstring>
        #include<iostream>
        using namespace std;
        struct point{
        	int x,y;
        }p[1010];
        double dp[1010][1010],d1,d2;
        int n,a,b;
        double dis(int i,int j){
        	return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
        }
        int main(){
        	freopen("paths.in","r",stdin);
        	freopen("paths.out","w",stdout);
        	scanf("%d%d%d",&n,&a,&b); a++; b++;
        	for(int i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y); 
        	p[n+1]=p[n];
        	for(int i=1;i<=n+2;i++)
        		for(int j=1;j<=n+2;j++) dp[i][j]=1e9;
        	dp[1][1]=0;
        	for(int i=1;i<=n;i++)
        		for(int j=1;j<=n;j++){
        			if(i==j&&i!=1) continue;
        			int k=max(i,j)+1;
        			if(k==n+1){
        				if(i==n) dp[i][k]=min(dp[i][k],dp[i][j]+dis(j,k));
        				else     dp[k][j]=min(dp[k][j],dp[i][j]+dis(i,k));
        			}
        			else if(k==a) dp[k][j]=min(dp[k][j],dp[i][j]+dis(i,k));
        			else if(k==b) dp[i][k]=min(dp[i][k],dp[i][j]+dis(j,k));
        			else dp[i][k]=min(dp[i][k],dp[i][j]+dis(j,k)),
        				 dp[k][j]=min(dp[k][j],dp[i][j]+dis(i,k));
        		}
        	printf("%.2lf",min(dp[n][n+1],dp[n+1][n]));
        	return 0;
        }
        

         

      • Prob 3(WA 3个点).线段树维护,注意细节啊 .

 

  • 下午
    • 迷了很久,很绝望
    • 入门OJ 3道题
      • 入门OJ 2028 [Noip模拟题]gcd区间

        可以暴力求出 f[i][j] 表示i-j区间的GCD
        ...
        打了一个RMQ,练练手

        代码:

        #include<cstdio>
        #include<cstring>
        #include<iostream>
        #define MAXN 1005
        using namespace std;
        int mi[1005];
        int val[1005][12];
        int gcd(int a,int b){
        	while(a^=b^=a^=b%=a);
        	return b;
        }
        int n,m;
        int main(){
        	scanf("%d%d",&n,&m);mi[1]=0;
        	for(int i=2;i<=1001;i++) mi[i]=mi[i>>1]+1;
        	for(int i=1;i<=n;i++) scanf("%d",&val[i][0]);
        	for(int j=1;(1<<j)<=n;j++)
        		for(int i=(1<<j);i<=n;i++)
        			val[i][j]=gcd(val[i-(1<<(j-1))][j-1],val[i][j-1]);
        	for(int i=1,l,r,k,ans;i<=m;i++){
        		scanf("%d%d",&l,&r);
        		k=mi[r-l+1];
        		ans=gcd(val[l+(1<<k)-1][k],val[r][k]);
        		printf("%d\n",ans);
        	}
        	return 0;
        }
        

         

      • 入门OJ 2029: [Noip模拟题]数列

        矩阵幂优化线性递推

      代码:
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      using namespace std;
      const int mod=1000000007;
      struct maxtrix{
      	int r,c;
      	int val[5][5];
      	maxtrix(){
      		r=c=0;
      		memset(val,0,sizeof(val));
      	}
      	void identity(int l){
      		r=c=l;
      		for(int i=1;i<=l;i++) val[i][i]=1;
      	}
      	maxtrix operator * (maxtrix const b){  // c==b.r
      		maxtrix now; now.r=r; now.c=b.c;
      		for(int i=1;i<=r;i++)
      			for(int j=1;j<=b.c;j++)
      				for(int k=1;k<=c;k++)
      					now.val[i][j]=(1ll*now.val[i][j]+1ll*val[i][k]*b.val[k][j])%mod; 
      		return now;
      	} 
      	maxtrix operator ^ (int b){
      		maxtrix base,now; base=*this;
      		now.identity(this->r); 
      		while(b){
      			if(b&1) now=now*base;
      			base=base*base;
      			b>>=1; 
      		}
      		return now;
      	}
      }g,d;
      int T,n; 
      int main(){
      	scanf("%d",&T);
      	while(T--){
      		d.r=1;d.c=3;
      		d.val[1][1]=d.val[1][2]=d.val[1][3]=1; 
      		scanf("%d",&n);
      		if(n<=3) printf("%d\n",d.val[1][n]);
      		else{
      			g.r=g.c=3;
      			g.val[1][1]=g.val[1][2]=g.val[2][2]=g.val[2][3]=g.val[3][1]=0;
      			g.val[1][3]=g.val[2][1]=g.val[3][2]=g.val[3][3]=1;
      			g=g^(n-3);
      			d=d*g;
      			printf("%d\n",d.val[1][3]);
      		}
      	}
      	return 0;
      }
      
      • 入门OJ 2030 [Noip模拟题]高级打字机

        弱弱版:

        因为不会撤销撤销操作,维护一个栈就好了。

        代码:

        #include<cstdio>
        #include<cstring>
        #include<iostream>
        using namespace std;
        char s[100005],com;
        int n,x,top;
        int main()
        {
            scanf("%d",&n);
        	for(int i=1;i<=n;i++){
                scanf(" %c",&com);
                if(com=='T') scanf(" %c",&s[++top]);
                else if(com=='U') scanf("%d",&x),top-=x;
                else scanf("%d",&x),printf("%c\n",s[x]);
            }
            return 0;
        } 

        强强版:

        主席树比较方便,每次操作之后都对应一颗区间线段树,

        形成主席树。

        undo时直接回到前j个历史版本即可

        代码:(学习大米饼大佬的,直接贴上了)

        #include<stdio.h>
        #include<cstring>
        #define go(i,a,b) for(int i=a;i<=b;i++)
        const int N=100003;
        struct Chair_Man_Tree{int l,r,word;}t[N*10];
        int q,Root[N],sz,rig[N],mid;
        void insert(int& u,int L,int R,int pos,char w){
            t[++sz]=t[u];u=sz;if(L==R){t[u].word=w;return;}mid=L+R>>1;
            pos>mid?insert(t[u].r,mid+1,R,pos,w):insert(t[u].l,L,mid,pos,w);
        }
        void find(int u,int L,int R,int pos){
            if(L==R){printf("%c\n",t[u].word);return;}mid=L+R>>1;
            pos>mid?find(t[u].r,mid+1,R,pos):find(t[u].l,L,mid,pos);
        }
        int main(){
            scanf("%d",&q);
        	int now=0,i=0;
        	go(I,1,q){
                char c1,c2;int j;scanf(" %c",&c1);
                if(c1=='T')i++,scanf(" %c",&c2),Root[i]=Root[i-1],insert(Root[i],1,N,++now,c2),rig[i]=now;
                if(c1=='U')i++,scanf("%d",&j),j=i-j-1,Root[i]=Root[j],now=rig[i]=rig[j];
                if(c1=='Q')scanf("%d",&j),find(Root[i],1,N,j);
            }
            return 0;
        }//Paul_Guderian 
  • 晚上
    • 入门OJ 3道题
      • 入门OJ 2031 [Noip模拟题]无线通讯网贪心:用"卫星"去填补两个距离大的村庄
        (最小生成树,kruskal算法),排序所有边,
        从小到大枚举边,去联通村庄,直到连通块数等于卫星线路数,
        则此时枚举的边为答案。
      代码:
      #include<cmath>
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #include<algorithm>
      using namespace std;
      struct point{
      	int x,y;
      }p[505];
      struct edge{
      	int u,v;
      	double val;
      	bool operator < (const edge &rtm) const{
      		return val<rtm.val;
      	}
      }e[505*505];
      int fa[505];
      int n,m,k,ent;
      double dis(int i,int j){
      	return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
      }
      int find(int x){
      	return fa[x]==x?x:fa[x]=find(fa[x]);
      }
      int main(){
      	scanf("%d%d",&k,&n);
      	for(int i=1;i<=n;i++) 
      		scanf("%d%d",&p[i].x,&p[i].y),fa[i]=i,m++;
      	for(int i=1;i<n;i++)
      		for(int j=i+1;j<=n;j++)
      			e[++ent]=(edge){i,j,dis(i,j)};
      	sort(e+1,e+ent+1);
      	for(int i=1,fu,fv;i<=ent;i++){
      		fu=find(e[i].u);
      		fv=find(e[i].v);
      		if(fu==fv) continue;
      		fa[fv]=fu;
      		m--;
      		if(k==m){
      			printf("%.2lf",e[i].val);
      			break;
      		}
      	}
      	return 0;
      }
    • 入门OJ 2033 [Noip模拟题]小K的农场

      差分约束
      列出不等式,化成最短路的dis定义表达:
      每个点的距离都小于等于能到它的点的距离+边权。

      1:(a,b,-c).
      2:(b,a,c).
      3:(a,b,0),(b,a,0)
      spfa判负环,存在负环则表明无解

      又学习了一下dfs版的spfa判负环(0 MS),比用优先队列优化后的bfs版(3100MS+)(这么慢,写错了么,没发现啊)快得多
      (可能是数据原因吧)

      代码:

      #include<queue>
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #define node(a,b) (node){a,b}
      using namespace std;
      struct edge{
      	int to,val,next;
      }e[10005*3];
      struct node{
      	int id,val;
      	bool operator <(const node &rtm) const{
      		return val>rtm.val;
      	}
      };
      int dis[10005],chg[10005],head[10005];
      bool inq[10005],fg;
      int n,m,ent=1; 
      void add(int u,int v,int w){
      	e[ent]=(edge){v,w,head[u]};
      	head[u]=ent++;
      }
      bool BFS_spfa(){
      	priority_queue<node> q; node u;
      	for(int i=1;i<=n;i++) q.push(node(i,0)),inq[i]=1;
      	while(!q.empty()){
      		u=q.top(); q.pop(); inq[u.id]=0;
      		for(int i=head[u.id];i;i=e[i].next){
      			int v=e[i].to;
      			if(dis[v]>dis[u.id]+e[i].val){
      				dis[v]=dis[u.id]+e[i].val;
      				if(++chg[v]>=n) return 0;
      				if(inq[v]) continue;
      				q.push(node(v,dis[v]));
      				inq[v]=1;
      			}
      		}
      	}
      	return 1;
      }
      void dfs(int u){
      	if(fg)return;
          inq[u]=1;
          for(int i=head[u];i;i=e[i].next){
              int v=e[i].to;
              if(dis[v]>dis[u]+e[i].val){
                  if(inq[v]){fg=1;return;}
                  dis[v]=dis[u]+e[i].val;
                  dfs(v);
              }
          }
          inq[u]=0;
      }
      bool DFS_spfa(){
      	fg=0;
      	for(int i=1;i<=n;i++) {
      		dfs(i);
      		if(fg) return 0;
      	}
      	return 1;
      }
      int main(){
      	scanf("%d%d",&n,&m);
      	for(int i=1,a,b,c,d;i<=m;i++){
      		scanf("%d",&a);
      		if(a==1) scanf("%d%d%d",&b,&c,&d),add(b,c,-d);
      		if(a==2) scanf("%d%d%d",&b,&c,&d),add(c,b,d);
      		if(a==3) scanf("%d%d",&b,&c),add(b,c,0),add(c,b,0);
      	}
      	if(/*BFS_spfa()*/DFS_spfa()) printf("Yes");
      	else printf("No");
      	return 0;
      }
    • 入门OJ 2034 [Noip模拟题]斐波那契数列

      又是一个水水题。

      矩阵幂优化线性递推

      特判(n<=2) 输出1
      会有n<2的输入...(坑,说好的n>=2呢)
      还有,n为long long型

      代码:

      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #define ll long long
      using namespace std;
      const int mod=1000000007;
      struct maxtrix{
      	int r,c;
      	int val[3][3];
      	maxtrix(){
      		r=c=0;
      		memset(val,0,sizeof(val));
      	}
      	void identity(int l){
      		r=c=l;
      		for(int i=1;i<=l;i++) val[i][i]=1;
      	}
      	maxtrix operator * (maxtrix const b){  // c==b.r
      		maxtrix now; now.r=r; now.c=b.c;
      		for(int i=1;i<=r;i++)
      			for(int j=1;j<=b.c;j++)
      				for(int k=1;k<=c;k++)
      					now.val[i][j]=(1ll*now.val[i][j]+1ll*val[i][k]*b.val[k][j])%mod; 
      		return now;
      	} 
      	maxtrix operator ^ (ll b){
      		maxtrix base,now; base=*this;
      		now.identity(this->r); 
      		while(b){
      			if(b&1) now=now*base;
      			base=base*base;
      			b>>=1; 
      		}
      		return now;
      	}
      }g,d;
      ll n; 
      int main(){
      	while(cin>>n){
      		if(n<=2){printf("1\n");continue;} 
      		g.r=g.c=2;
      		g.val[1][1]=0;g.val[1][2]=g.val[2][1]=g.val[2][2]=1;
      		d.r=1;d.c=2;
      		d.val[1][1]=d.val[1][2]=1;
      		g=g^(n-2);
      		d=d*g;
      		printf("%d\n",d.val[1][2]);
      	}
      	return 0;
      }
  • 最后的皮皮话
    • 下午效率不高,得再集中精神点。(中午睡久了吧……)
    • 从考试来看,有些常用的东西和知识点要复习啊,不然学了白学一样。
    • 做题时要多考虑,否则到处都是漏洞。 
    • 刷题速度要加快呢,时间不多了。
posted @ 2017-09-29 15:31  *ZJ  阅读(196)  评论(0编辑  收藏  举报