zoukankan      html  css  js  c++  java
  • [noip][2014]

    Day1t1

    思路

    就是模拟,只是怎样更优雅的模拟而已,不过多点if也没关系,能拿分才是关键嘛。

    代码:

    #include<cstdio>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    int read() {
    	int x=0,f=1;
    	char c=getchar();
    	while(!isdigit(c)) {
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(isdigit(c)) {
    		x=x*10+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    const int N=210;
    int pd[10][10];
    void pre() {
    	pd[0][2]=pd[0][3]=pd[1][3]=pd[2][4]=pd[3][4]=1;
    	for(int i=0;i<=4;++i)
    		for(int j=0;j<i;++j)
    			pd[i][j]=pd[j][i]^1;
    }
    int a[N],b[N];
    int main() {
    	pre();
    	int na,nb,n;
    	scanf("%d%d%d",&n,&na,&nb);
    	for(int i=0;i<na;++i)
    		scanf("%d",&a[i]);
    	for(int i=0;i<nb;++i) 
    		scanf("%d",&b[i]);
    	int ansa=0,ansb=0,ajs=0,bjs=0;
    	for(int i=1;i<=n;++i) {
    		ajs%=na;
    		bjs%=nb;
    		ansa+=pd[a[ajs]][b[bjs]];
    		ansb+=pd[b[bjs]][a[ajs]];
    		ajs++;
    		bjs++;
    	}
    	printf("%d %d
    ",ansa,ansb);
    	return 0;
    }
    

    Day1t2

    思路

    仔细理解题意可以发现,其实题目就是让着对于每个点,将其所能到达的每个点两两相乘,求出所得之和和最大值。如果每个点都n方枚举的话应该是过不了的。所以可以稍微推一下O(n)计算的方法,其实就是一边对前面的孩子求前缀和,一边乘当前的孩子,最后再乘2即可。总复杂度似乎是(O(n^2))的,但是发现因为这是一棵树,所以对于每条边只会计算到两次,实际复杂度是(O(n))的。

    最大值不取模,最大值不取模,最大值不取模

    代码:

    #include<cstdio>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int N=200000+1000,mod=10007;
    ll read() {
        ll x=0,f=1;
        char c=getchar();
        while(!isdigit(c)) {
            if(c=='-') f=-1;
            c=getchar();
        }
        while(isdigit(c)) {
            x=x*10+c-'0';
            c=getchar();
        }
        return x*f;
    }
    struct node
    {
        int v,nxt;
    }e[N*2];
    int ejs;
    int head[N];
    int w[N];
    int ans,sum;
    void add(int u,int v) {
        e[++ejs].v=v;e[ejs].nxt=head[u];head[u]=ejs;
    }
    int K=0;
    void work(int x) {
        int kk=0;
        int mx=-1,tmx=-1;
        for(int i=head[x];i;i=e[i].nxt)
            kk+=w[e[i].v];
        for(int i=head[x];i;i=e[i].nxt) {
            K++;
            int v=e[i].v;
            sum+=(kk-w[v])*w[v]%mod;
            sum%=mod;
            if(w[v]>mx) {
                tmx=mx;
                mx=w[v];
            }
            else if(w[v]>tmx) tmx=w[v];
        }
        ans=max(ans,mx*tmx);
    }
    int main() {
        int n=read();
        for(int i=1;i<n;++i) {
            int x=read(),y=read();
            add(x,y);
            add(y,x);
        }
        for(int i=1;i<=n;++i) w[i]=read();
        for(int i=1;i<=n;++i) work(i);
        printf("%d %d
    ",ans,sum);
        return 0;
    }
    

    Day1t3

    75分思路

    用f[i][j]表示到位置i,高度为j所需要花费的最小点击次数。然后每次利用当前可以存在的位置去更新下一个位置即可。复杂度(O(nmk))

    100分思路

    在上面思路的基础上可以发现,第三层枚举,也就是枚举下一层可能存在的位置的时候,可以不必从当前位置转移,而是从下一位置已经转移了的位置进行转移。比如现在位置是1,每点击一下会上生2,那么下一位置位于5的最小点击次数可以不用f[i][1]+2更新,而是用f[i+1][3]+1,明显f[i+1][3]之前已经被更新过了。需要注意的是,小鸟再升到最高处之后,可以继续点击,只不过不会再升了而已,需要特殊处理一下。

    代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int N=10100,INF=0x3f3f3f3f;
    int f[N][3010],X[N],Y[N],a[N],L[N],H[N];
    int n,m,K;
    int js,bzz[N];
    int read() {
    	int x=0,f=1;
    	char c=getchar();
    	while(!isdigit(c)) {
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(isdigit(c)) {
    		x=x*10+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    int main() {
    	n=read(),m=read(),K=read();
    	memset(f,0x3f,sizeof(f));
    	for(int i=0;i<n;++i) {
    		H[i]=m+1;
    		X[i]=read();
    		Y[i]=read();
    	}
    	H[n]=m+1;
    	for(int i=1;i<=K;++i) {
    		int x=read();
    		bzz[x]=1;
    		L[x]=read();
    		H[x]=read();
    	}
    	for(int i=1;i<=m;++i)
    		f[0][i]=0;
    	for(int i=1;i<=n;++i) {
    		for(int j=X[i-1]+1;j<=m+X[i-1];++j)
    			f[i][j]=min(f[i][j-X[i-1]]+1,f[i-1][j-X[i-1]]+1);
    		for(int j=m+1;j<=m+X[i-1];++j)
    			f[i][m]=min(f[i][m],f[i][j]);
    		for(int j=1;j<=m-Y[i-1];++j) 
    			f[i][j]=min(f[i][j],f[i-1][j+Y[i-1]]);
    		for(int j=1;j<=L[i];++j)
    			f[i][j]=INF;
    		for(int j=H[i];j<=m;++j)
    			f[i][j]=INF;
    		int bz=0;
    		for(int j=L[i];j<H[i];++j) {
    			if(f[i][j]<INF) {
    				bz=1;
    				break;
    			}
    		}
    		if(bz==0) {
    			printf("0
    %d
    ",js);
    			return 0;
    		}
    		if(bzz[i]) js++;
    	}
    	int ans=INF;
    	for(int i=L[n]+1;i<H[n];++i) ans=min(ans,f[n][i]);
    	printf("1
    %d
    ",ans);
    	return 0;
    }
    

    Day2t1

    思路

    考虑到数据范围很小,可以枚举每个路口,然后在扫一遍。去看如果将网络发射器安在当前位置会有多少收益,取最大值即可。复杂度(O(n^4))

    代码

    #include<cstdio>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    ll a[200][200];
    int d;
    int n;
    ll work(int x,int y) {
    	ll ans=0;
    	for(int i=max(x-d,0);i<=min(x+d,128);++i)
    		for(int j=max(y-d,0);j<=min(y+d,128);++j)
    			ans+=a[i][j];
    	return ans;
    }
    ll read() {
    	ll x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) {x=x*10+c-'0';c=getchar();}
    	return x;
    }
    ll ans,pans;
    int main() {
    	d=read();n=read();
    	for(int i=1;i<=n;++i) {
    		int x=read(),y=read(),z=read();
    		a[x][y]=z;
    	}
    	for(int x=0;x<=128;++x) {
    		for(int y=0;y<=128;++y) {
    			ll z=work(x,y);
    			if(z>ans) pans=1,ans=z;
    			else if(z==ans) pans++;
    		}
    	}
    	printf("%lld %lld
    ",pans,ans);
    	return 0;
    }
    

    Day2t2

    思路

    建反边,先在反边跑一边bfs找出可以走的边,然后在正着bfs即可。记得以前发过一篇比较详细的博客

    代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=300000;
    int S,T,n,m,head1[N],head2[N],js1,js2;
    int vis[5][N];
    struct node {
    	int v,nxt;
    }e1[N],e2[N];
    void add1(int u,int v) {
    	e1[++js1].v=v;e1[js1].nxt=head1[u];head1[u]=js1;
    }
    void add2(int u,int v) {
    	e2[++js2].v=v;e2[js2].nxt=head2[u];head2[u]=js2;
    }
    queue<int>q;
    int dis[N];
    void bfs1() {
    	vis[1][T]=1;
    	while(!q.empty()) q.pop();
    	q.push(T);
    	while(!q.empty()) {
    		int u=q.front();
    		q.pop();
    		for(int i=head2[u];i;i=e2[i].nxt) {
    			int v=e2[i].v;
    			if(!vis[1][v]) q.push(v),vis[1][v]=1;
    		}
    	}
    }
    void bfs2() {
    	dis[S]=0;
    	while(!q.empty()) q.pop();
    	if(vis[2][S]==0)
    	q.push(S);
    	while(!q.empty()) {
    		int u=q.front();
    		q.pop();
    		for(int i=head1[u];i;i=e1[i].nxt) {
    			int v=e1[i].v;
    			if(vis[2][v]==1) continue;
    			if(dis[v]==-1) dis[v]=dis[u]+1,q.push(v);
    			if(v==T) return;
    		}
    	}
    }
    int main() {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;++i) {
    		int x,y;
    		scanf("%d%d",&x,&y);
    		if(x==y) continue;
    		add1(x,y);
    		add2(y,x);
    	}
    	scanf("%d%d",&S,&T);
    	bfs1();
    	for(int i=1;i<=n;++i) {
    		for(int j=head1[i];j;j=e1[j].nxt) {
    			if(vis[1][e1[j].v]==0) {
    				vis[2][i]=1;
    				break;
    			}
    		}
    	}
    	memset(dis,-1,sizeof(dis));
    	bfs2();
    	cout<<dis[T];
    	return 0;
    }
    

    Day2t3

    思路

    这数据给的真的很微妙。数组a这么大,也是很吓人啊。但是仔细一想就可以知道,如果找到的x满足给出a[i]数组的话,那么即使对a[i]数组取模,依然可以满足方程。所以就可以写个读优,然后将a[i]取模即可。然后就是枚举x带入了。如果直接用快速幂计算的话,复杂度达到了(O(nmlog(m)))所以就可以依次将每个x提出来(详见秦九韶算法),就可以O(n)计算了。

    代码

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=110,mod=1e9+7;
    typedef long long ll;
    ll a[N];
    int n,m;
    ll read() {
    	ll x=0,f=1; char c=getchar();
    	while(!isdigit(c)) {
    		if(c=='-') f=-1;
    		c=getchar();
    	} 
    	while(isdigit(c)) {
    		x=x*10+c-'0';
    		x%=mod;
    		c=getchar();
    	}
    	return x*f;
    }
    ll work(int now,int x) {
    	ll ans=0;
    	for(int i=now;i>=1;--i) {
    		ans=(ans+a[i])*x%mod;
    	}
    	return ans+a[0]%mod;
    }
    int ans[2000000];
    int main() {
    	n=read();m=read();
    	for(int i=0;i<=n;++i)
    		a[i]=read();
    	int js=0;
    	for(int i=1;i<=m;++i)
    		if(work(n,i)==0) ans[++js]=i;
    	printf("%d
    ",js);
    	for(int i=1;i<=js;++i) {
    		printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    

    总结

    这年的题目是比较简单的,但是题面里面全是细节,一不注意就100分变0分了。

  • 相关阅读:
    window.onload和document.ready/jquery页面加载事件等的区别
    JAVA面试题大全
    BIO NIO AIO的知识扫盲
    类的加载过程详细解释
    nginx的Rewrite和其他相关配置
    【微服务架构设计】DDD
    【重构】
    【多线程】Lock接口与其实现类
    【三方件】汇总
    【SpringBoot-SpringSecurity】安全响应头+防攻击 ~~ TODO
  • 原文地址:https://www.cnblogs.com/wxyww/p/9724521.html
Copyright © 2011-2022 走看看