P3336 [ZJOI2013] 话旧

/*
f[0]=0,f[n]=0,所有极小值==0,且都是斜率+-1的直线 若干点固定 问1.有多少种方法2.最大值<=         
因为 刻画斜率 f[i][0/1] 当前处理i点 之前是up/down 即i-1 down/up
len=x2-x1-y1-y2;
1.x1-x2==y1-y2  add(f[i][0],f[i-1][0]); if(y1==0)add(f[i][0],f[i-1][1]);
2.x1-x2==y2-y1  add(f[i][1],f[i-1][0]+f[i-1][1]);
3.len<0 add(f[i][1],f[i-1][0]);    if(y1==0)add(f[i][1],f[i-1][1]);
4.len==0 add(f[i][1],f[i-1][0]); if(y1==0)add(f[i][1],f[i-1][1]); add(f[i][0],f[i-1][0]+f[i-1][1]);                   
5.len>0 (len%2== 0/1都一样)
    ll t=(2*f[i-1][0]+f[i-1][1])*qpow(2,len/2-1)%mod;
    if(y2>0)add(f[i][0],t);
    add(f[i][1],t);//虽然少了一个齿 但多了一个齿缝*2 所以依然成立

最大值
a+b=x2-x1 a-b=y2-y1 -> if(f[i][1]) y1+a=0.5*(x2-x1+y1+y2)         

:::x0/x1...不能用 用x_0...代替
:::unique 有< = 两种限制 
*/
/*
2 0

1 2

6 9
4 2
4 2
2 0
4 2
6 0
5 1
2 0
0 0
0 0

1 2

*/

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string.h>
#include<queue>
#include<vector>
#include<bits/stdc++.h>
typedef long long ll;
#define ddd printf("-----------------------\n");
using namespace std;
const int mod=19940417;
const int MAXK=1000010;

struct Point
{
    int x,y;
    bool operator <(const Point &a)const{
        return x<a.x;
    }
    bool operator ==(const Point &a)const{
        return x==a.x;
    }
}p[MAXK];

ll f[MAXK][2];
ll qpow(ll a,ll b)
{
    ll ret=1;
    while(b)
    {
        if(b%2)ret=ret*a%mod;
        b/=2;
        a=a*a%mod;
    }
    return ret;
}
void add(ll &x,ll y){
    for(x+=y;x>=mod;x-=mod);
}

int main()
{
    int n,k,tmax=0;
    scanf("%d%d",&n,&k);
    p[k+1].x=n;
    for(int i=1;i<=k;i++)scanf("%d%d",&p[i].x,&p[i].y);
    sort(p,p+k+2);//p[0].x/y==0
    k=unique(p,p+k+2)-p -1;
    f[0][1]=1;
    for(int i=1;i<=k;i++)
    {
        int x_1=p[i-1].x,y_1=p[i-1].y;
        int x_2=p[i].x,y_2=p[i].y;
        int len=x_2-x_1-y_1-y_2;
        if(x_1-x_2==y_1-y_2)
        {
            add(f[i][0],f[i-1][0]);
            if(y_1==0)add(f[i][0],f[i-1][1]);
        }
        else if(x_1-x_2==y_2-y_1)
        {
            add(f[i][1],f[i-1][0]+f[i-1][1]);
        }
        else if(len<0)
        {
            add(f[i][1],f[i-1][0]);
            if(y_1==0)add(f[i][1],f[i-1][1]);
        }
        else if(len==0)
        {
            add(f[i][1],f[i-1][0]);
            if(y_1==0)add(f[i][1],f[i-1][1]);
            add(f[i][0],f[i-1][0]+f[i-1][1]);
        }
        else
        {
            ll t=(2*f[i-1][0]+f[i-1][1])*qpow(2,len/2-1)%mod;
            if(y_2>0)add(f[i][0],t);
            add(f[i][1],t);
        }
        if(f[i][1])  
            tmax=max(tmax,(x_2-x_1+y_1+y_2)/2);    
    }
    printf("%lld %d\n",f[k][1],tmax);
    return 0;
}

 

posted @ 2023-12-12 04:17  JMXZ  阅读(10)  评论(0)    收藏  举报