• [CLYZ2017]day12


    跳马

    Description
    有一张无穷大,没有边界的棋盘,你要将马从\((0,0)\)移动到\((x,y)\).
    每一步你可以使马的横坐标,纵坐标其中一个\(\pm1\),另一个\(\pm2\).
    你需要求出最少步数.有\(t\)组数据.
    Input
    第一行一个正整数\(t\),接下来\(t\)行每行两个整数\(x,y\).
    Output
    \(t\)行,每行一个整数表示答案.
    Sample Input

    8
    1 2
    2 1
    1 -2
    2 -1
    -1 2
    -2 -1
    -2 1
    -1 -2
    

    Sample Output

    1 1 1 1 1 1 1 1
    

    HINT
    \(1\leq{t}\leq1000,|x|,|y|\leq10^9\).

    Solution

    100分

    打表找个规律.(虽然是可以证明的).

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define M 8
    #define N 1001
    using namespace std;
    typedef long long ll;
    int x[M]={-2,-2,-1,-1,1,1,2,2};
    int y[M]={1,-1,2,-2,2,-2,1,-1};
    int a[N][N];
    queue<int> qx,qy;
    inline int read(){
    	int ret=0;char c=getchar();
    	while(!isdigit(c))
    		c=getchar();
    	while(isdigit(c)){
    		ret=(ret<<1)+(ret<<3)+c-'0';
    		c=getchar();
    	}
    	return ret;
    }
    inline void bfs(int u,int v){
    	a[u][v]=1;
    	qx.push(u);qy.push(v);
    	while(!qx.empty()){
    		u=qx.front();qx.pop();
    		v=qy.front();qy.pop();
    		for(int i=0,j,k;i<M;++i){
    			j=u+x[i];k=v+y[i];
    			if(j>=0&&j<N&&k>=0&&k<N&&!a[j][k]){
    				a[j][k]=a[u][v]+1;
    				qx.push(j);qy.push(k);
    			}
    		}
    	}
    }
    inline void Aireen(){ 
    	bfs(20,20);
    	for(int i=0;i<=40;++i){
    		for(int j=0;j<=40;++j)
    			printf("%d\t",a[i][j]-1);
    		printf("\n");
    	}
    	return;
    	int x,y,t;
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d%d",&x,&y);
    		printf("%d\n",a[x+20][y+20]-1);
    	}
    }
    int main(){
    	freopen("jump.in","r",stdin);
    	freopen("test.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
    • code
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int x,y,t;
    inline void Aireen(){ 
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d%d",&x,&y);
    		x=abs(x);y=abs(y);
    		if(x>y) swap(x,y);
    		if(!x){
    			if(!y) puts("0");
    			else if(y==1) puts("3");
    			else if(y==2) puts("2");
    			else if(y==3) puts("3");
    			else printf("%d\n",y/4*2+y%4); 
    		}
    		else if(y>=(x<<1)){
    			y-=(x<<1);
    			printf("%d\n",x+y/4*2+y%4);
    		}
    		else if(x>=4){
    			y-=x;x-=4;
    			if(!(x%3)){
    				if(!y) printf("%d\n",(2+x/3)*2);
    				else printf("%d\n",(2+x/3)*2-1+(y-1)/3+(y-1)%3);
    				
    			}
    			else if(x%3==1){
    				if(!y) printf("%d\n",(2+x/3)*2);
    				else if(y==1) printf("%d\n",(2+x/3)*2+1);
    				else printf("%d\n",(2+x/3)*2+(y-2)/3+(y-2)%3);
    			}
    			else printf("%d\n",(2+x/3)*2+y/3+y%3);
    		}
    		else{
    			if(x==1) puts("2");
    			else if(x==2) printf("%d\n",6-y); 
    			else if(x==3) printf("%d\n",y-1);
    		}
    	}
    }
    int main(){
    	freopen("jump.in","r",stdin);
    	freopen("jump.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    绝对值

    Description
    \(n\)个实数\(x_i\),其中\(x_i\)\([l_i,r_i]\)中均匀随机.
    你需要求出\(|\sum{x_i}|\)的期望.答案对\(998244353\)取模.
    Input
    第一行一个正整数\(n\).接下来\(n\)行每行两个整数\(l_i,r_i\).
    Output
    一行一个整数表示答案.
    Sample Input

    2 
    -2 3
    -2 1
    

    Sample Output

    199648872
    

    HINT
    \(-10^6\leq{l_i}\leq{r_i}\leq{10^6}\).

    Solution

    100分

    我不会...先贴份闫神的题解...
    \(f(i,x)\)表示|前\(i\)个变量的和-\(x\)|的期望.
    显然这是一个分段多项式函数,每一段可以通过对\(f(i-1)\)积分得到.
    \(f(i)\)的段点为\(f(i-1)\)的段点减去\(l_i\)或加上\(r_i\).
    时间复杂度\(O(\sum(2^i\times{i^2}))=O(2^n\times{n^2})\).

    序列

    Description
    给定正整数\(m\)以及长度为\(n\)的序列对\((a_i,b_i)\),你需要将它分为若干段,满足以下\(2\)个条件:

    1. \(i<j\)\(i\)\(j\)不在一段中,则\(b_i>a_j\).
    2. 每一段的\(a\)的最大值之和\(\leq{m}\).

    在此基础上,你需要最小化每一段的\(b\)的和的最大值.
    Input
    第一行两个正整数\(n,m\),接下来\(n\)行每行两个正整数\(a_i,b_i\).
    Output
    一行一个整数表示答案.
    Sample Input

    4 6
    4 3
    3 5
    2 5
    2 4
    

    Sample Output

    9
    

    HINT
    \(n\leq100000,m\leq10^{12},1\leq{a_i,b_i}\leq2\times10^9\).

    Solution

    100分

    条件一等价于若\(i<j\)\(b_i\leq{a_j}\),则\(i\)\(j\)在一段中.
    合并这样的段.
    二分每一段的\(b\)的和的最大值\(mx\).
    最小化每一段的\(a\)的最大值之和.
    \(f[i]\)表示前\(i\)个数的\(a\)的最大值之和的最小值.
    \(f[i]=min\{f[j]+mx[j+1][i]\}\).
    \(set\)维护一个\(a\)的下降序列,每次把\(set\)不合法的\(a_i\)弹出.
    显然会影响当前决策的是满足\(s[i]-s[j]\leq{mx}\)最小的\(j\),以及\(set\)中的最小值.

    #include<set>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 100005
    #define max(a,b) a>b?a:b
    #define min(a,b) a<b?a:b
    using namespace std;
    typedef long long ll;
    ll a[N],b[N],f[N],mx[N],m,l,r,mi,mid;
    int q[N],h,t,n,cnt;
    multiset<ll> s;
    inline bool chk(ll k){
    	ll sum=0ll;int l=0;h=1;t=0;
    	for(int i=1;i<=n;++i){
    		while(h<=t&&a[i]>=a[q[t]]){
    			if(h<t) s.erase(s.find(f[q[t-1]]+a[q[t]]));
    			--t;
    		}
    		q[++t]=i;
    		if(h<t) s.insert(f[q[t-1]]+a[q[t]]);
    		sum+=b[i];
    		while(sum>k) sum-=b[++l];
    		while(h<=t&&l>=q[h]){
    			if(h<t) s.erase(s.find(f[q[h]]+a[q[h+1]]));
    			++h;
    		}
    		f[i]=f[l]+a[q[h]];
    		if(h<t) f[i]=min(f[i],*s.begin());
    	}
    	s.clear();
    	return f[n]<=m; 
    } 
    inline void Aireen(){
    	scanf("%d%lld",&n,&m);
    	for(int i=1;i<=n;++i)
    		scanf("%lld%lld",&a[i],&b[i]);
    	for(int i=n;i;--i)
    		mx[i]=max(mx[i+1],a[i]);
    	for(int i=1,j;i<=n;i=j){
    		mi=b[i];
    		for(j=i+1;j<=n&&mi<=mx[j];++j)
    			mi=min(mi,b[j]);
    		a[++cnt]=a[i];b[cnt]=b[i];
    		for(int k=i+1;k<j;++k){
    			a[cnt]=max(a[cnt],a[k]);b[cnt]+=b[k];
    		}
    	}
    	n=cnt;
    	for(int i=1;i<=n;++i){
    		l=max(l,b[i]);r+=b[i];
    	}
    	while(l<r){
    		mid=(l+r)>>1;
    		if(chk(mid)) r=mid;
    		else l=mid+1;
    	}
    	printf("%lld\n",l); 
    }
    int main(){
    	freopen("sequence.in","r",stdin);
    	freopen("sequence.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    在CentOS7上部署Kubernetes集群
    使用Ansible部署etcd 3.2高可用集群
    shiro框架学习-3- Shiro内置realm
    shiro框架学习-2-springboot整合shiro及Shiro认证授权流程
    shiro框架学习-1-shiro基本概念
    markdown编辑器常用命令
    华为云服务器centos7.3安装tomcat
    华为云服务器centos7.3 安装jdk
    springboot2.0+mysql整合mybatis,发现查询出来的时间比数据库datetime值快了8小时
    使用IDEA自动生成Java实体类
  • 原文地址:https://www.cnblogs.com/AireenYe/p/CLYZ2017day12.html
Copyright © 2020-2023  润新知