携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情
[ZJOI2013]话旧
题目描述
小林跟着银河队选手去了一趟宇宙比赛,耳濡目染,变得学术起来。回来后,他发现世界大变样了。比丘兽究级进化,成了凤凰兽;金先生因为发了一篇 paper,一跃成为教授,也成为了银河队选拔委员会成员。
一日,小林与金教授聊天。金教授回忆起过去的岁月,那些年他学过的电路原理。他曾经对一种三角波很感兴趣,并且进行了一些探究。小林感到很好奇,于是金教授就将课题形式化地说了一遍。
有一定义在 的连续函数 ,其中 是整数,满足 ,它的所有极值点在整数处取到,且 的极小值均是 。对于任意的 到 间的整数 , 在 上是斜率为 或 的一次函数。
金先生研究的是,若他知道其中 个整点的函数值,那么:
- 有多少个函数满足条件?
- 满足条件的函数中, 的最大值,最大能是多少?
小林思考了一下,便想出了很好的算法。那么作为经过多年训练的你呢?
输入格式
第一行包含两个用空格隔开的整数 。接下来 行,每行两个整数,表示 和 。
输出格式
一行两个整数,分别对应两个问题的答案。考虑到第一问答案可能很大,你只要输出它除以 的余数。
样例 #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
提示
- 对于 的数据,。
- 对于 的数据,。
- 对于 的数据,,。
- 对于 的数据,,。
- 对于 的数据,。
- 另有 的数据,。
- 对于 的数据,,。
#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;
}