Codeforces 水題選刷
阿新 • • 發佈:2019-01-06
翻譯會給出在程式碼中
Ctrl+F點開網頁搜尋,直接查題號即可
有一些很棒的題我會單獨拿出來寫題解的,特別水的題就不做了嘻嘻嘻
Codeforces 938C
/*
題解:
給定兩個正整數n,m(m≤n),對於一個n階0-1方陣,
其任意m階子方陣中至少有一個元素“0”,則可以求解這個方陣中的“1”的最大數目。現求解這個問題的逆向問題:已知這個最大數目為X,求相應的n和m。
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int n,m;
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int x;scanf("%d",&x);
if(x==0){printf("1 1\n");continue;}
bool bk=false;
for(int i=1;i*i<=x;i++)
{
int j=x/i;
if(i*j==x && ((i&1 )==(j&1)))
{
n=(i+j)/2;
int temp=n-i;
if(temp==0)continue;
m=n/temp;
if(n>=m && (n/m)==temp)
{
printf("%d %d\n",n,m);
bk=true;
break ;
}
}
}
if(bk==false)printf("-1\n");
}
return 0;
}
Codeforces 938D
/*
翻譯:
給定一張包含n(n<=2*10^5)個節點的圖,給出m(m<=2*10^5)條雙向邊,邊有權,每個點也有權
對於每個點i,你要輸出i到任意一個點再回來的最小代價,到達那個點時要加入那個點的點權,經過則不用
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long LL;
LL d[210000];
struct pt
{
int x;
friend bool operator <(pt n1,pt n2){return d[n1.x]>d[n2.x];}
};
priority_queue<pt> q;
inline LL read()
{
LL f=1,x=0;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node
{
LL c;
int x,y,next;
}a[810000];int len,last[210000];
void ins(int x,int y,LL c)
{
len++;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len;
}
int n,m,st;
bool v[210000];
int main()
{
n=read();m=read();st=n+1;
len=0;memset(last,0,sizeof(last));
for(int i=1;i<=m;i++)
{
int x=read(),y=read();LL c=read();
ins(x,y,2*c);ins(y,x,2*c);
}
for(int i=1;i<=n;i++)
{
LL x=read();
ins(st,i,x);
}
memset(d,63,sizeof(d));d[st]=0;
memset(v,false,sizeof(v));v[st]=true;
pt tmp;tmp.x=st;q.push(tmp);
while(!q.empty())
{
tmp=q.top();int x=tmp.x;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(d[y]>d[x]+a[k].c)
{
d[y]=d[x]+a[k].c;
if(v[y]==false)
{
v[y]=true;
pt cnt;cnt.x=y;q.push(cnt);
}
}
}
q.pop();v[x]=false;
}
for(int i=1;i<n;i++)printf("%lld ",d[i]);
printf("%lld\n",d[n]);
return 0;
}
Codeforces 939E
/*
翻譯:
給出Q(Q<=5*10^5)個操作,共有兩種操作
第一種操作輸入兩個數op x:op表示第幾種操作,x表示在當前序列中插入數x(x<=10^9),保證x大於當前序列中任意一個數
第二種操作輸入一個數op:op表示第幾種操作,求當前序列中的Maximize
定義Maximize為:在當前序列中找出一個子集,Maximize表示子集中數最大值/子集平均數的最大值
輸出保留10位小數
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
LL sum[510000],f[510000],list[510000];
int T,head;
int main()
{
head=0;
scanf("%d",&T);
while(T--)
{
int op;LL x;
scanf("%d",&op);
if(op==1)
{
scanf("%I64d",&list[++head]);
sum[head]=sum[head-1]+list[head];
}
else
{
int l=1,r=head;
while(l<r-1)
{
int mid=(l+r)/2;
int mmid=(mid+r)/2;
if((double)(list[head]+sum[mid])/(mid+1)>(double)(list[head]+sum[mmid])/(mmid+1))l=mid;
else r=mmid;
}
if((double)(list[head]+sum[l])/(l+1)>(double)(list[head]+sum[r])/(r+1))printf("%.10lf\n",(double)list[head]-(double)(list[head]+sum[r])/(r+1));
else printf("%.10lf\n",(double)list[head]-(double)(list[head]+sum[l])/(l+1));
}
}
return 0;
}
Codeforces 940F
/*
翻譯:
給出一個長度為n(n<=100000)的序列,序列中每個數a[i]<=10^9
設c[i]表示第i種數出現的次數
q(q<=100000)次詢問,詢問共有兩種
第一種 1 x y 表示求序列中x~y c[i]的mex。mex表示最小的沒有出現過的值(不包括0)
第二種 2 x y 表示把序列中第x位的數替換為y
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
map<int,int> q;
int val[210000],len;
int l,r,t;
struct pck{int p,c,las;}ch[210000];int chlen;
struct ask
{
int l,r,t,op;
}A[210000];int n,m,alen;
int block,pos[210000];
bool cmp(ask n1,ask n2)
{
if(pos[n1.l]!=pos[n2.l])return pos[n1.l]<pos[n2.l];
if(pos[n1.r]!=pos[n2.r])return pos[n1.r]<pos[n2.r];
return n1.t<n2.t;
}
int vis[210000];//sum[i]的出現次數
int col[210000],las[210000],answer[210000],ans;//las[i]表示第i個位置上一次的顏色
int sum[210000];//每種數出現了多少次
void upd_col(int now,int c)
{
if(now>=l && now<=r)vis[sum[col[now]]]--,sum[col[now]]--,vis[sum[col[now]]]++;
col[now]=c;
if(now>=l && now<=r)vis[sum[col[now]]]--,sum[col[now]]++,vis[sum[col[now]]]++;
}
void del(int now)
{
vis[sum[col[now]]]--;
sum[col[now]]--;
vis[sum[col[now]]]++;
}
void add(int now)
{
vis[sum[col[now]]]--;
sum[col[now]]++;
vis[sum[col[now]]]++;
}
int gtans(){for(int i=1;;i++)if(vis[i]==0)return i;}
int main()
{
scanf("%d%d",&n,&m);
block=ceil(pow(n,2.0/3));
for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1;
for(int i=1;i<=n;i++)
{
scanf("%d",&col[i]);
val[++len]=col[i];las[i]=col[i];
}
for(int i=1;i<=m;i++)
{
int op,u,v;
scanf("%d%d%d",&op,&u,&v);
if(op==1)
{
alen++;
A[alen].l=u;A[alen].r=v;A[alen].t=chlen;
A[alen].op=i-chlen;
}
else
{
chlen++;ch[chlen].p=u;ch[chlen].c=v;
ch[chlen].las=las[u];las[u]=v;
val[++len]=v;
}
}
sort(val+1,val+1+len);
len=unique(val+1,val+1+len)-val-1;
for(int i=1;i<=len;i++)q[val[i]]=i;
for(int i=1;i<=chlen;i++)ch[i].las=q[ch[i].las],ch[i].c=q[ch[i].c];
for(int i=1;i<=n;i++)col[i]=q[col[i]];
sort(A+1,A+1+alen,cmp);
l=A[1].l,r=A[1].r,t=A[1].t;
for(int i=1;i<=A[1].t;i++)col[ch[i].p]=ch[i].c;
for(int i=A[1].l;i<=A[1].r;i++)
{
vis[sum[col[i]]]--;
sum[col[i]]++;
vis[sum[col[i]]]++;
}
for(int i=1;;i++)if(vis[i]==0){answer[A[1].op]=i;break;}
for(int i=2;i<=alen;i++)
{
while(t<A[i].t)t++,upd_col(ch[t].p,ch[t].c);
while(t>A[i].t)upd_col(ch[t].p,ch[t].las),t--;
while(l<A[i].l)del(l++);
while(l>A[i].l)add(--l);
while(r<A[i].r)add(++r);
while(r>A[i].r)del(r--);
answer[A[i].op]=gtans();
//for(int j=l;j<=r;j++)printf("%d ",col[j]);
}
for(int i=1;i<=alen;i++)printf("%d\n",answer[i]);
return 0;
}
Codeforces 946D
/*
翻譯:
定義一個星期n(n<=500)天,一天m(m<=500)個小時。給定課表,你想翹課,但最多隻能翹K(K<=500)節課
定義一天在學校的時間為(該天最後一節課時間-該天第一節課時間+1)
你想要這個星期呆在學校的時間儘量短,求這個最短時間
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
char ch[510][510];
int sum[510][510];//第i天 翹j節課
int f[510][510];//前i天 翹j節課
int n,m,K,a[510],s[510],gt[510];
int pre[510];
int main()
{
scanf("%d%d%d",&n,&m,&K);
for(int i=1;i<=n;i++)
{
int cnt=0;
scanf("%s",ch[i]+1);
for(int j=1;j<=m;j++)a[j]=ch[i][j]-'0';
for(int j=1;j<=m;j++){if(a[j]==1)gt[++cnt]=j,s[i]++;}
if(cnt!=0)sum[i][0]=m-(gt[cnt]-gt[1]+1);
else {sum[i][0]=m;continue;}
for(int j=1;j<=s[i];j++)//翹多少節課
{
if(j==s[i]){sum[i][j]=m;break;}
int u=s[i]-j;//上多少節課
for(int k=1;k<=cnt-u+1;k++)
sum[i][j]=max(sum[i][j],m-(gt[k+u-1]-gt[k]+1));
}
}
f[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=K;j++)
for(int k=0;k<=min(K,s[i]);k++)
{
if(j>=k)f[i][j]=max(f[i-1][j-k]+sum[i][k],f[i][j]);
}
printf("%d\n",n*m-f[n][K]);
return 0;
}
Codeforces 946E
/*
翻譯:
定義一個數為美麗數,當且僅當這個數長度為偶數,且他的某一個排列可以組成一個迴文數
給出n(n<=2*10^100000),求小於n的最大美麗數
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
char ch[210000];
int a[210000],g[15],len;
int f[210000][10];
void sol()
{
for(int i=len;i>=1;i--)
for(int j=a[i]-1;j>=0;j--)
{
if(i==1 && j==0)break;
int cnt=0,maxx=0;
for(int k=0;k<=9;k++)
{
int op=0;if(k==j)op=1;
if(f[i-1][k]^op==1)cnt++,maxx=k;
}
if(len-i<cnt)continue;
for(int k=1;k<=i-1;k++)printf("%d",a[k]);
printf("%d",j);
for(int k=i+1;k<=len-cnt;k++)printf("9");
int t=maxx;
for(int k=len-cnt+1;k<=len;k++)
{
int op=0;if(t==j)op=1;else op=0;
while(f[i-1][t]^op!=1){t--;if(t==j)op=1;else op=0;}
printf("%d",t);t--;
}
printf("\n");
return ;
}
for(int i=1;i<len-2;i++)printf("9");
printf("\n");
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(g,0,sizeof(g));
scanf("%s",ch+1);len=strlen(ch+1);
for(int i=1;i<=len;i++)a[i]=ch[i]-'0',g[a[i]]++;
if(len%2==1)
{
for(int i=1;i<len;i++)printf("9");
printf("\n");continue;
}
if((g[1]==1 && g[0]==len-1 && a[1]==1) || (g[1]==2 && g[0]==len-2 && a[1]==1 && a[len]==1))
{
for(int i=1;i<len-1;i++)printf("9");
printf("\n");continue;
}
for(int i=0;i<=9;i++)f[0][i]=0;//0 偶數次
for(int i=1;i<=len;i++)
for(int j=0;j<=9;j++)
{
if(a[i]==j)f[i][j]=f[i-1][j]^1;
else f[i][j]=f[i-1][j];
}
sol();
}
return 0;
}
Codeforces 946F
/*
翻譯:
定義f[i]=f[i-1]+f[i-2],+表示拼接的意思,即為f[i-1]與f[i-2]拼接起來組成f[i]
給出一個子串(長度<=100),求這個子串在fn(n<=100)的**子序列**中出現了多少次
答案對1e9+7取模
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
LL f[110][110][110];
LL lenth[110];//新增2^lenth[i]次方個數
char ch[110];int n,m;
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",ch+1);
for(int i=1;i<=n;i++)f[ch[i]-'0'][i][i]=1;
lenth[0]=lenth[1]=2;
for(int i=2;i<=m;i++)lenth[i]=(lenth[i-1]*lenth[i-2])%mod;
for(int i=2;i<=m;i++)
for(int l=1;l<=n;l++)
for(int r=l;r<=n;r++)
{
LL opx,opy;
if(l==1)opx=lenth[i-1];else opx=1;
if(r==n)opy=lenth[i-2];else opy=1;
f[i][l][r]=(f[i][l][r]+(opx*f[i-2][l][r]+opy*f[i-1][l][r])%mod)%mod;
for(int k=l;k<r;k++)
f[i][l][r]=(f[i][l][r]+f[i-1][l][k]*f[i-2][k+1][r])%mod;
}
printf("%lld\n",f[m][1][n]);
return 0;
}
Codeforces 946G
/*
翻譯:
給出一個長度為n(n<=10^5)的序列,要求最少的次數,使得序列變為一個刪去一個數後嚴格上升的序列
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int f[2][210000];//沒刪 刪
int n,pos,ans;
int main()
{
scanf("%d",&n);
memset(f,63,sizeof(f));
f[0][0]=-1e9;
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
int t=upper_bound(f[1]+1,f[1]+1+n,x-i+1)-f[1];
f[1][t]=x-i+1;ans=max(ans,t);
f[1][pos]=min(f[1][pos],f[0][pos]);ans=max(ans,pos);
t=upper_bound(f[0]+1,f[0]+1+n,x-i)-f[0];
f[0][pos=t]=x-i;
}
printf("%d\n",max(0,n-ans-1));
return 0;
}
Codeforces 950B
/*
翻譯:
給出兩個數字串a,b,長度分別為n,m(n,m<=10^6)
求之多能把a,b分成多少部分,使得每一部分分別相等
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int a[1100000],b[1100000];
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=m;i++)scanf("%d",&b[i]);
int i=0,j=0,sx=0,sy=0,ans=0;
while(i+1<=n && j+1<=m)
{
i++;j++;
sx+=a[i];sy+=b[j];
while(sx!=sy)
{
if(sx<sy)sx+=a[++i];
else sy+=b[++j];
}
ans++;sx=sy=0;
}
printf("%d\n",ans);
return 0;
}
Codeforces 954A
/*
給定一段長度為n(n<=100)的字串,R與U可以組合在一起,求組合在一起後最短字串長度
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
char ch[110];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",ch+1);
int i=1,cnt=0;
while(i<=n)
{
if((ch[i]=='R' && ch[i+1]=='U') || (ch[i]=='U' && ch[i+1]=='R'))cnt++,i+=2;
else cnt++,i+=1;
}
printf("%d\n",cnt);
return 0;
}
Codeforces 954B
/*
翻譯:
給定一個字串,每次可以輸入1個字元(低端操作)或進行之多一次高階操作
高階操作:複製當前字串並插入至當前字串末尾
求可以弄出這個字串的最小總運算元
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
char ch[110];
int n;
int main()
{
scanf("%d",&n);
scanf("%s",ch+1);
int ans=n;
for(int i=1;i<=n;i++)
{
bool bk=false;
for(int j=i+1;j<=i+i;j++)if(ch[j]!=ch[j-i]){bk=true;break;}
if(bk==false)ans=min(ans,n-2*i+1+i);
}
printf("%d\n",ans);
return 0;
}
Codeforces 954C
/*
翻譯:
定義一個矩陣u*v由1~u*v組成,位置(i,j)填值(i-1)*v+j。每個格子可以向上下左右走(邊界你懂得)
給出一段路線,判斷這條路線是否可以在某一個矩陣中走出。不能輸出NO,能則輸出YES以及某個矩陣的u,v
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int n;
int a[210000];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(i==1)continue;
if(a[i]==a[i-1]){printf("NO\n");return 0;}
}
if(n==1)
{
printf("YES\n1 %d\n",a[1]);
return 0;
}
int x,y,t=1,sx=-1,sy=-1;
for(int i=2;i<=n;i++)if(abs(a[i]-a[i-1])!=1){sy=abs(a[i]-a[i-1]);break;}
if(sy==-1)
{
int maxx=0;
for(int i=1;i<=n;i++)maxx=max(maxx,a[i]);
printf("YES\n1 %d\n",maxx);
return 0;
}
x=(a[1]-1)/sy+1;y=(a[1]-1)%sy+1;
sx=max(sx,x);
bool bk=false;
while(t<=n)
{
t++;if(t>n)break;
if(a[t]==a[t-1]+1)
{
if(sy==-1 || y<sy)y++;
else{bk=true;break;}
}
else if(a[t]==a[t-1]-1)
{
if(y==1){bk=true;break;}
else y--;
}
else
{
if(a[t]>a[t-1])
{
int tmp=a[t]-a[t-1];
if(sy==-1 || sy==tmp)sy=tmp;
else {bk=true;break;}
x++;
}
else
{
int tmp=a[t-1]-a[t];
if(sy==-1 || sy==tmp)sy=tmp;
else {bk=true;break;}
x--;
if(x==0){bk=true;break;}
}
}
sx=max(sx,x);
}
if(bk==true || (sx>1e9 || sy>1e9))printf("NO\n");
else printf("YES\n%d %d\n",sx,sy);
return 0;
}
Codeforces 954D
/*
翻譯:
給出一張圖,點數n(n<=1000),邊數m(m<=1000)。
給出兩個點s,t,要在圖內新增一條邊並保證s->t的最短路徑長度不改變
求這樣的邊有多少條
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
int x,y,next;
}a[2100];int len,last[1100];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
int n,m,stx,sty;
bool v[1100];
int d[2][1100],list[1100],head,tail,st;
void spfa(int op)
{
memset(v,false,sizeof(v));v[st]=true;
memset(d[op],63,sizeof(d[op]));d[op][st]=0;
list[1]=st;head=1;tail=2;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(d[op][y]>d[op][x]+1)
{
d[op][y]=d[op][x]+1;
if(v[y]==false)
{
v[y]=true;
list[tail++]=y;
if(tail==n+1)tail=1;
}
}
}
head++;if(head==n+1)head=1;
v[x]=false;
}
}
bool mp[1100][1100];
int main()
{
scanf("%d%d%d%d",&n,&m,&stx,&sty);
memset(mp,false,sizeof(mp));len=0;memset(last,0,sizeof(last));
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);mp[x][y]=mp[y][x]=true;
ins(x,y);ins(y,x);
}
st=stx;spfa(0);
st=sty;spfa(1);
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)if(i!=j && mp[i][j]==false)
{
mp[i][j]=mp[j][i]=true;
if(d[0][i]+d[1][j]+1>=d[0][sty] && d[0][j]+d[1][i]+1>=d[0][sty])ans++;
}
printf("%d\n",ans);
return 0;
}
Codeforces 954E
/*
翻譯:
給定n(n<=2*10^5)個水龍頭,第i個水龍頭有最大出水量a[i](a[i]<=10^6),且給定一個溫度值t[i](t[i]<=10^6)。
定義一次出水得到的溫度為Sigma(a[i]*t[i])/Sigama(a[i]),給定一次出水得到的溫度,求最大總出水量。
如果得不到該溫度,輸出0
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
int n,T;
struct node
{
LL a,t;
}P[1110000];
bool cmp(node n1,node n2){return n1.t<n2.t;}
int main()
{
scanf("%d%d",&n,&T);
for(int i=1;i<=n;i++)scanf("%lld",&P[i].a);
for(int i=1;i<=n;i++)scanf("%lld",&P[i].t);
LL sx=0,sy=0,ax=0,ay=0;
for(int i=1;i<=n;i++)
{
if(P[i].t>T)sx+=P[i].a*(P[i].t-T),ax+=P[i].a;
else if(P[i].t<T)sy+=P[i].a*(T-P[i].t),ay+=P[i].a;
}
double ans=0;LL sum=0;
if(sx<sy)//負的多
{
ans=(double)ax;sum=sx;
sort(P+1,P+1+n,cmp);
int tmp=n;
for(int i=1;i<=n;i++)if(P[i].t>=T){tmp=i-1;break;}
for(int i=tmp;i>=1;i--)
{
if(sum-P[i].a*(T-P[i].t)>0)sum-=P[i].a*(T-P[i].t),ans+=(double)P[i].a;
else
{
ans+=(double)sum/(T-P[i].t);
sum=0;
break;
}
}
for(int i=1;i<=n;i++)if(P[i].t==T)ans+=(double)P[i].a;
if(sum==0)printf("%.15lf\n",ans);
else printf("0\n");
}
else
{
ans=(double)ay;sum=sy;
sort(P+1,P+1+n,cmp);
int tmp=1;
for(int i=n;i>=1;i--)if(P[i].t<=T){tmp=i+1;break;}
for(int i=tmp;i<=n;i++)
{
if(sum-P[i].a*(P[i].t-T)>0)sum-=P[i].a*(P[i].t-T),ans+=(double)P[i].a;
else
{
ans+=(double)sum/(P[i].t-T);
sum=0;
break;
}
}
for(int i=1;i<=n;i++)if(P[i].t==T)ans+=(double)P[i].a;
if(sum==0)printf("%.15lf\n",ans);
else printf("0\n");
}
return 0;
}
Codeforces 954F
/*
翻譯:
給定一個3行m(m<=10^18)列的矩陣,從格子(i,j)可以移到(i,j+1)與(i-1(i>1),j+1),(i+1(i<3),j+1)
矩陣內會存在n個位於a[i]行,座標l[i]~r[i]的障礙物,障礙物不能通行
求從格子(2,1)移動至(2,m)的方案數,答案對1e9+7取模
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
struct node
{
LL l,r;int a;
}P[11000];
LL s[21000];
int t,c[5][41000],pre[5];
int n;LL m;
struct matrix
{
LL m[5][5