[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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 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=0&&j=0&&k
  • code
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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\(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\(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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 100005
#define max(a,b) a>b?a:b
#define min(a,b) a 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(hk) sum-=b[++l];
        while(h<=t&&l>=q[h]){
            if(h>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;
}