【动态规划】话旧

73 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

[ZJOI2013]话旧

题目描述

小林跟着银河队选手去了一趟宇宙比赛,耳濡目染,变得学术起来。回来后,他发现世界大变样了。比丘兽究级进化,成了凤凰兽;金先生因为发了一篇 paper,一跃成为教授,也成为了银河队选拔委员会成员。

一日,小林与金教授聊天。金教授回忆起过去的岁月,那些年他学过的电路原理。他曾经对一种三角波很感兴趣,并且进行了一些探究。小林感到很好奇,于是金教授就将课题形式化地说了一遍。

有一定义在 [0,N][0,N] 的连续函数 f(x)f(x),其中 NN 是整数,满足 f(0)=f(N)=0f(0)=f(N)=0,它的所有极值点在整数处取到,且 f(x)f(x)极小值均是 00。对于任意的 00N1N-1 间的整数 IIf(x)f(x)(I,I+1)(I, I+1) 上是斜率为 111-1 的一次函数。

金先生研究的是,若他知道其中 KK 个整点的函数值,那么:

  1. 有多少个函数满足条件?
  2. 满足条件的函数中,f(x)f(x) 的最大值,最大能是多少?

小林思考了一下,便想出了很好的算法。那么作为经过多年训练的你呢?

输入格式

第一行包含两个用空格隔开的整数 N,KN,K。接下来 KK 行,每行两个整数,表示 xix_if(xi)f(x_i)

输出格式

一行两个整数,分别对应两个问题的答案。考虑到第一问答案可能很大,你只要输出它除以 19 940 41719\ 940\ 417 的余数。

样例 #1

样例输入 #1

2 0

样例输出 #1

1 1

样例 #2

样例输入 #2

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

样例输出 #2

1 2

提示

  • 对于 10%10\% 的数据,N10N \leq 10
  • 对于 20%20\% 的数据,N50N \leq 50
  • 对于 30%30\% 的数据,N100N \leq 100K100K \leq 100
  • 对于 50%50\% 的数据,N103N \leq 10^3K103K \leq 10^3
  • 对于 70%70\% 的数据,N105N \leq 10^5
  • 另有 10%10\% 的数据,K=0K=0
  • 对于 100%100\% 的数据,0N109 0 \leq N \leq 10^90K1060 \leq K \leq 10^6
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=19940417,Maxn=1e6+5;
inline int read(){
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+ch-'0',ch=getchar(); 
	return s*w;
}
struct node{
	int x,y;
}a[Maxn];	
bool operator<(node a,node b){return a.x<b.x;}
bool operator==(node a,node b){return a.x==b.x&&a.y==b.y;}
int n,k,f[Maxn][2],ans;
inline int power(int a,int b){
	int dat=1;
	for(;b;b>>=1){
		if(b&1)dat=dat*a%mod;
		a=a*a%mod;
	}
	return dat;
}
signed main(){
	n=read(),k=read();
	for(int i=1;i<=k;i++)a[i].x=read(),a[i].y=read();
	k++,a[k].x=0,a[k].y=0;
	k++,a[k].x=n,a[k].y=0;
	sort(a+1,a+k+1);
	k=unique(a+1,a+k+1)-a-1;
	f[1][1]=1;
	for(int i=1;i<k;i++){
		int w=(a[i+1].x-a[i].x-a[i+1].y-a[i].y)>>1;
		if(a[i+1].y-a[i].y==a[i+1].x-a[i].x)f[i+1][0]=(f[i][0]+(a[i].y?0:f[i][1]))%mod;
		else if(a[i+1].y-a[i].y==a[i].x-a[i+1].x)f[i+1][1]=(f[i][1]+f[i][0])%mod;
		else if(w<0)f[i+1][1]=(f[i][0]+(a[i].y?0:f[i][1]))%mod;
		else if(w==0)f[i+1][0]=(f[i][1]+f[i][0])%mod,f[i+1][1]=f[i][0];
		else{
			int p=power(2,w-1);
			if(a[i+1].y)f[i+1][0]=(f[i][1]+2*f[i][0])%mod*p%mod;
			f[i+1][1]=(f[i][1]+2*f[i][0])%mod*p%mod;
		}
		if(f[i+1][1]||a[i+1].y==0)ans=max(ans,(a[i+1].x-a[i].x+a[i].y+a[i+1].y)>>1);
	}
	printf("%lld %lld",f[k][1],ans);
	return 0;
}