zoukankan      html  css  js  c++  java
  • 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
          ",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
        ",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
        ",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
          ",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
          ",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
        ");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
        ",d.val[1][2]);
        	}
        	return 0;
        }
    • 最后的皮皮话
      • 下午效率不高,得再集中精神点。(中午睡久了吧……)
      • 从考试来看,有些常用的东西和知识点要复习啊,不然学了白学一样。
      • 做题时要多考虑,否则到处都是漏洞。 
      • 刷题速度要加快呢,时间不多了。
  • 相关阅读:
    【C#进阶系列】06 类型和成员基础
    纪中5日T1 1564. 旅游
    纪中17日T1 2321. 方程
    纪中17日T2 2322. capacitor
    纪中10日T1 2313. 动态仙人掌
    纪中14日听课小结 图论 最短路 二分图 差分约束
    一个抓猫的游戏 消遣GAME 持续更新中!
    洛谷P1464 Function  HDU P1579 Function Run Fun
    洛谷P1976 鸡蛋饼
    纪中12日T1 2307. 选择
  • 原文地址:https://www.cnblogs.com/zj75211/p/7611254.html
Copyright © 2011-2022 走看看