版权声明:本文为博主原创文章,欢迎转载并注明来源。 https://blog.csdn.net/w_weilan/article/details/82768705
Magic Mirror
#include <cstdio>
#include <cstring>
int T;
char s[20],a[20]="JESSIE",b[20]="jessie";
bool o;
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%s",s);
if (strlen(s)!=6)
{
printf("Dare you say that again?\n");
continue;
}
o=true;
for (int i=0;i<6;i++)
if ((s[i]!=a[i])&&(s[i]!=b[i]))
{
o=false;
break;
}
if (o) printf("Good guy!\n");
else printf("Dare you say that again?\n");
}
return 0;
}
Mathematical Curse
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int t,n,m,k;
long long a[1010];
char s[10];
long long mx[1010][10],mn[1010][10];
int main()
{
scanf("%d",&t);
while (t--)
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
scanf("%s",s);
memset(mx,0,sizeof(mx));
memset(mn,0,sizeof(mn));
mx[0][0]=mn[0][0]=k;
for (int i=1;i<=n;i++)
for (int j=1;(j<=m)&&(j<=i);j++)
{
mx[i][0]=mn[i][0]=k;
if (s[j-1]=='+') mx[i][j]=mx[i-1][j-1]+a[i],mn[i][j]=mn[i-1][j-1]+a[i];
else if (s[j-1]=='-') mx[i][j]=mx[i-1][j-1]-a[i],mn[i][j]=mn[i-1][j-1]-a[i];
else if (s[j-1]=='*')
{
if (a[i]>=0) mx[i][j]=mx[i-1][j-1]*a[i],mn[i][j]=mn[i-1][j-1]*a[i];
else mx[i][j]=mn[i-1][j-1]*a[i],mn[i][j]=mx[i-1][j-1]*a[i];
}
else
{
if (a[i]>=0) mx[i][j]=mx[i-1][j-1]/a[i],mn[i][j]=mn[i-1][j-1]/a[i];
else mx[i][j]=mn[i-1][j-1]/a[i],mn[i][j]=mx[i-1][j-1]/a[i];
}
if (i>j) mx[i][j]=max(mx[i][j],mx[i-1][j]),mn[i][j]=min(mn[i][j],mn[i-1][j]);
}
printf("%lld\n",mx[n][m]);
}
return 0;
}
Password
Sequence
Jiu Yuan Wants to Eat
链剖+双标记维护区间和,区间取反操作等价于区间乘-1
后区间加-1
。
时限卡的有点紧,线段树一开始用vector建的时候会T,改成数组也要跑2700ms/3000ms。
#include<cstdio>
#include<vector>
using namespace std;
typedef unsigned long long ll;
const int N=2e5+9;
struct Node
{
ll sum,add,mul;
} v[N<<2];
struct SegmentTree
{
SegmentTree(int N)
{
build(1,N,1);
}
void build(int l,int r,int rt)
{
v[rt]= {0,0,1};
if(l==r)return;
int m=l+r>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
}
void push_down(int rt,ll ln,ll rn)
{
v[rt<<1]= {v[rt<<1].sum*v[rt].mul+v[rt].add*ln,v[rt<<1].add*v[rt].mul+v[rt].add,v[rt<<1].mul*v[rt].mul};
v[rt<<1|1]= {v[rt<<1|1].sum*v[rt].mul+v[rt].add*rn,v[rt].mul*v[rt<<1|1].add+v[rt].add,v[rt<<1|1].mul*v[rt].mul};
v[rt]= {v[rt].sum,0,1};
}
void add(int L,int R,ll C,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
v[rt].add+=C;
v[rt].sum+=C*(r-l+1);
return;
}
int m=(l+r)/2;
push_down(rt,m-l+1,r-m);
if(L<=m)add(L,R,C,l,m,rt<<1);
if(R>m)add(L,R,C,m+1,r,rt<<1|1);
v[rt].sum=v[rt<<1].sum+v[rt<<1|1].sum;
}
void mul(int L,int R,ll C,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
v[rt].mul*=C;
v[rt].add*=C;
v[rt].sum*=C;
return;
}
int m=l+r>>1;
push_down(rt,m-l+1,r-m);
if(L<=m)mul(L,R,C,l,m,rt<<1);
if(R>m)mul(L,R,C,m+1,r,rt<<1|1);
v[rt].sum=v[rt<<1].sum+v[rt<<1|1].sum;
}
ll ask(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)return v[rt].sum;
int m=l+r>>1;
push_down(rt,m-l+1,r-m);
ll ans=0;
if(L<=m)ans+=ask(L,R,l,m,rt<<1);
if(R>m)ans+=ask(L,R,m+1,r,rt<<1|1);
return ans;
}
};
struct Graph
{
struct Vertex
{
vector<int> a,b;//相关出边和入边编号
int siz,dep,top,dfn;//树链剖分中使用,依次代表子树节点数、深度、所在链的顶端节点、dfs序
};
struct Edge
{
int from,to;
//ll dist,cap;//边长、容量,图论算法使用
};
vector<Vertex> v;//点集
vector<Edge> e;//边集
Graph(int n):v(n) {}
void add(const Edge &ed)
{
//if(ed.from==ed.to)return;//如果有需要请拆点
v[ed.from].a.push_back(e.size());
v[ed.to].b.push_back(e.size());
e.push_back(ed);
}
};
struct Tree:Graph
{
Tree(int n):Graph(n) {}
int fa(int k,int i=0)
{
return e[v[k].b[i]].from;
}
int ch(int k,int i=0)
{
return e[v[k].a[i]].to;
}
void build(int u,const Graph &g)//无向图dfs建树,且重边在最前,u为根节点
{
v[u].siz=1;
for(int i=0,w,k; i!=g.v[u].a.size(); ++i)
if(k=g.v[u].a[i],w=g.e[k].to,!v[w].siz)//没访问过的点siz默认0
{
build(w,g);
v[u].siz+=v[w].siz;
add(g.e[k]);
if(v[ch(u)].siz<v[w].siz)//重边移到最前
swap(v[u].a.front(),v[u].a.back());
}
}
};
struct Diagram:Tree
{
SegmentTree data;
Diagram(const Graph &g,int root):
Tree(g.v.size()),data(g.v.size())
{
build(root,g);
int cnt=v[root].dfn=v[root].dep=1;
dfs(v[root].top=root,cnt);
}
void dfs(int u,int &cnt)
{
for(int i=0,w; i!=v[u].a.size(); ++i)
{
v[w=ch(u,i)].dfn=++cnt;
v[w].top=i?w:v[u].top;
v[w].dep=v[u].dep+1;
dfs(w,cnt);
}
}
ll ask(int x,int y)
{
ll ans=0;
for(; v[x].top!=v[y].top; x=fa(v[x].top))
{
if(v[v[x].top].dep<v[v[y].top].dep)swap(x,y);
ans+=data.ask(v[v[x].top].dfn,v[x].dfn,1,v.size(),1);
}
if(v[x].dep<v[y].dep)swap(x,y);
return ans+=data.ask(v[y].dfn,v[x].dfn,1,v.size(),1);
}
void add(int x,int y,ll pv)
{
for(; v[x].top!=v[y].top; x=fa(v[x].top))
{
if(v[v[x].top].dep<v[v[y].top].dep)swap(x,y);
data.add(v[v[x].top].dfn,v[x].dfn,pv,1,v.size(),1);
}
if(v[x].dep<v[y].dep)swap(x,y);
data.add(v[y].dfn,v[x].dfn,pv,1,v.size(),1);
}
void mul(int x,int y,ll pv)
{
for(; v[x].top!=v[y].top; x=fa(v[x].top))
{
if(v[v[x].top].dep<v[v[y].top].dep)swap(x,y);
data.mul(v[v[x].top].dfn,v[x].dfn,pv,1,v.size(),1);
}
if(v[x].dep<v[y].dep)swap(x,y);
data.mul(v[y].dfn,v[x].dfn,pv,1,v.size(),1);
}
};
int main()
{
for(int n; ~scanf("%d",&n);)
{
Graph g(n+1);
for(int i=2,b; i<=n; ++i)
scanf("%d",&b),g.add({b,i});
Diagram d(g,1);
scanf("%d",&n);
for(int i=0,u,v; i<n; ++i)
{
ll x;
scanf("%llu%d%d",&x,&u,&v);
if(x==1)scanf("%llu",&x),d.mul(u,v,x);
else if(x==2)scanf("%llu",&x),d.add(u,v,x);
else if(x==3)d.mul(u,v,-1),d.add(u,v,-1);
else printf("%llu\n",d.ask(u,v));
}
}
}
Modular Production Line
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll N=100009,NPOS=-1,INF=1e18;
struct Ranker:vector<ll>
{
void init()
{
sort(begin(),end()),resize(unique(begin(),end())-begin());
}
int ask(ll x)const
{
return lower_bound(begin(),end(),x)-begin();
}
};
struct Graph
{
struct Vertex
{
vector<int> a/*,b*/;//相关出边和入边编号
//int siz,dep,top,dfn;//树链剖分中使用,依次代表子树节点数、深度、所在链的顶端节点、dfs序
};
struct Edge
{
int from,to;
ll dist,cap;//边长、容量,图论算法使用
};
vector<Vertex> v;//点集
vector<Edge> e;//边集
Graph(int n):v(n) {}
void add(const Edge &ed)
{
if(ed.from==ed.to)return;//如果有需要请拆点
v[ed.from].a.push_back(e.size());
//v[ed.to].b.push_back(e.size());
e.push_back(ed);
}
};
struct EdmondKarp:Graph
{
ll flow,cost;
vector<ll> f;
EdmondKarp(int n):Graph(n) {}
void add(Edge ed)
{
Graph::add(ed);
swap(ed.from,ed.to),ed.cap=0,ed.dist*=-1;
Graph::add(ed);
}
void ask(int s,int t)
{
vector<int> p(v.size(),NPOS);
for(f.assign(e.size(),flow=cost=0);;)
{
vector<ll> d(v.size(),INF);
vector<int> flag(v.size(),d[s]=0);
for(deque<int> q(flag[s]=1,s); !q.empty(); q.pop_front())
for(int u=q.front(),i=flag[u]=0,k,to; i<v[u].a.size(); ++i)
if(k=v[u].a[i],to=e[k].to,
e[k].cap>f[k]&&d[to]>d[u]+e[k].dist)
{
d[to]=d[u]+e[k].dist,p[to]=k;
if(!flag[to])q.push_back(to),flag[to]=1;
}
if(d[t]==INF)return;
ll _f=INF;
for(int u=t; u!=s; u=e[p[u]].from)
_f=min(_f,e[p[u]].cap-f[p[u]]);
for(int u=t; u!=s; u=e[p[u]].from)
cost+=_f*e[p[u]].dist,f[p[u]]+=_f,f[p[u]^1]-=_f;
flow+=_f;
}
}
};
int t,n,m,k,x[N],y[N],w[N];
int main()
{
for(scanf("%d",&t); t--;)
{
Ranker rk;
scanf("%d%d%d",&n,&k,&m);
for(int i=0; i<m; ++i)
{
scanf("%d%d%d",&x[i],&y[i],&w[i]);
rk.push_back(x[i]);
rk.push_back(++y[i]);
}
rk.init();
EdmondKarp g(rk.size()+2);
for(int i=0; i<rk.size(); ++i)g.add({i,i+1,0,k});
for(int i=0; i<m; ++i)g.add({rk.ask(x[i]),rk.ask(y[i]),-w[i],1});
g.add({rk.size()+1,0,0,k});
g.ask(rk.size()+1,rk.size());
printf("%lld\n",-g.cost);
}
}
Give Candies
答案是 ,用费马小定理把指数对M-1取模后进行运算避免更多的高精度运算。
#include<stdio.h>
#define mul(a,b,c) (1LL*(a)*(b)%(c))
typedef int ll;
const ll M=1e9+7;
ll pow(ll a,ll b,ll m)
{
ll r=1;
for(a%=m; b; b>>=1,a=mul(a,a,m))
if(b&1)r=mul(r,a,m);
return r;
}
char s[100009];
int t,n;
int main()
{
for(scanf("%d",&t); t--;)
{
scanf("%s",s);
for(int i=n=0; s[i]; ++i)
n=mul(n,10,M-1)+s[i]-'0';
printf("%d\n",pow(2,n+M-2,M));
}
}
String and Times
拉一个后缀数组的板子跑掉了。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
struct SufArr
{
vector<int> sa,rk,h;
SufArr(const vector<int> &s,int m):sa(s.size(),0),rk(s),h(s.size(),0)
{
vector<int> cnt(s.size()+m,0);
for(int i=0; i<s.size(); ++i)++cnt[rk[i]];
for(int i=1; i<m; ++i)cnt[i]+=cnt[i-1];
for(int i=0; i<s.size(); ++i)sa[--cnt[rk[i]]]=i;
for(int k=1,j=0; k<=s.size()&&j<s.size()-1; k<<=1)
{
for(int i=0; i<s.size(); ++i)
{
if(j=sa[i]-k,j<0)j+=s.size();
h[cnt[rk[j]]++]=j;
}
cnt[0]=sa[h[0]]=j=0;
for(int i=1; i<s.size(); ++i)
{
if(rk[h[i]]!=rk[h[i-1]]||rk[h[i]+k]!=rk[h[i-1]+k])
cnt[++j]=i;
sa[h[i]]=j;
}
swap(rk,sa),swap(sa,h);
}
for(int i=0,k=0,j=rk[0]; i<s.size()-1; ++i,++k)
for(; ~k&&s[i]!=s[sa[j-1]+k]; j=rk[sa[j]+1],--k)
h[j]=k;
}
};
struct SparseTable
{
typedef int ll;
vector<vector<ll> > f;
SparseTable(const vector<ll> &a):f(log2(a.size())+1,a)
{
for(int k=0; k+1<f.size(); ++k)
for(int i=0; i+(1<<k)<a.size(); ++i)
f[k+1][i]=min(f[k][i],f[k][i+(1<<k)]);
}
ll ask(int l,int r)
{
int k=log2(r-l+1);
return min(f[k][l],f[k][r+1-(1<<k)]);
}
};
ll cal(SufArr &sa,SparseTable &st,int k)//原串中至少出现k次的子串数量
{
ll ans=0;
if(k>1)
for(int l=2,r=k; r<sa.h.size(); ++l,++r)
ans+=max(st.ask(l,r)-sa.h[l-1],0);
else
for(int i=1; i<sa.h.size(); ++i)
ans+=sa.h.size()-1-sa.sa[i]-sa.h[i];
return ans;
}
char s[2000009];
int main()
{
for(int a,b; ~scanf("%s%d%d",s,&a,&b);)
{
SufArr sa(vector<int>(s,s+strlen(s)+1),'Z'+1);
SparseTable st(sa.h);
printf("%lld\n",cal(sa,st,a)-cal(sa,st,b+1));
}
}
Save the Room
#include<stdio.h>
int main()
{
for(int a,b,c; ~scanf("%d%d%d",&a,&b,&c);)
printf(a%2&&b%2&&c%2?"No\n":"Yes\n");
}
Participate in E-sports
交了个高精度开根号上去。
#include<cmath>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
struct Wint:vector<int>//继承vector
{
static const int width=9,base=1e9;
Wint(unsigned long long n=0)//普通初始化,当整型数和Wint同时运算时会提升至Wint
{
for(; n; n/=base)push_back(n%base);
}
explicit Wint(const string &s)//字符串初始化函数,未判断字符串合法情况
{
for(int len=int(s.size()-1)/width+1,b,e,i=0; i!=len; ++i)
for(e=s.size()-i*width,b=max(0,e-width),push_back(0); b!=e; ++b)
back()=back()*10+s[b]-'0';
trim(0);
}
Wint& trim(bool up=1)//去前导0,是否需要进位,很常用的小函数,为方便返回自身
{
for(int i=1; up&&i<size(); ++i)
{
if(at(i-1)<0)--at(i),at(i-1)+=base;
if(at(i-1)>=base)at(i)+=at(i-1)/base,at(i-1)%=base;
}
while(!empty()&&back()<=0)pop_back();
for(; up&&!empty()&&back()>=base; at(size()-2)%=base)
push_back(back()/base);
return *this;
}
};
istream& operator>>(istream &is,Wint &n)
{
string s;//懒
return is>>s,n=Wint(s),is;
}
bool operator<(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return a.size()<b.size();
for(int i=a.size()-1; ~i; --i)
if(a[i]!=b[i])return a[i]<b[i];
return 0;
}
bool operator>(const Wint &a,const Wint &b)
{
return b<a;
}
bool operator<=(const Wint &a,const Wint &b)
{
return !(a>b);
}
bool operator>=(const Wint &a,const Wint &b)
{
return !(a<b);
}
Wint& operator+=(Wint &a,const Wint &b)
{
a.resize(max(a.size(),b.size()));//保证有足够的位数
for(int i=0; i!=b.size(); ++i)a[i]+=b[i];
return a.trim();//单独进位防自运算
}
Wint operator+(Wint a,const Wint &b)
{
return a+=b;
}
Wint& operator++(Wint &a)//前置版本
{
return a+=1;//懒
}
Wint operator++(Wint &a,int)//后置版本
{
Wint b=a;
return ++a,b;
}
Wint& operator-=(Wint &a,const Wint &b)//a<b会使a变为0
{
a.resize(max(a.size(),b.size()));//保证有足够的位数
for(int i=0; i!=b.size(); ++i)a[i]-=b[i];
return a.trim();//单独进位防自运算
}
Wint operator-(Wint a,const Wint &b)
{
return a-=b;
}
Wint& operator--(Wint &a)//前置版本
{
return a-=1;//懒
}
Wint operator--(Wint &a,int)//后置版本
{
Wint b=a;
return --a,b;
}
Wint& operator*=(Wint &a,const Wint &b)
{
vector<unsigned long long> n(a.size()+b.size()+2,0);//防爆int,多开位用于进位
for(int j=0; j!=b.size(); ++j)
if(b[j])//稀疏优化,特殊情况很有效
for(int i=0; i!=a.size(); ++i)
n[i+j]+=(unsigned long long)a[i]*b[j];
for(int i=1; i<n.size(); ++i)//这里用<防止位数0,单独进位防自运算
n[i]+=n[i-1]/a.base,n[i-1]%=a.base;
while(!n.empty()&&!n.back())n.pop_back();
return a.assign(n.begin(),n.end()),a;
}
Wint operator*(Wint a,const Wint &b)
{
return a*=b;
}
Wint& operator/=(Wint &a,Wint b)
{
Wint r,c,d=b.base/(b.back()+1);
a*=d,b*=d,c.assign(a.size(),0);
for(int i=a.size()-1; ~i; --i)
{
r.insert(r.begin(),a[i]);
unsigned long long s=0;
for(int j=b.size(); j+1>=b.size(); --j)//b.size()==0肯定第一行就出问题的
s=s*b.base+(j<r.size()?r[j]:0);
for(d=c[i]=s/b.back(),d*=b; r<d; r+=b)--c[i];
r-=d;
}
return swap(a,c),a.trim(0);//r为加倍后的余数,可通过高精度除低精度得到真正余数,此处略
}
Wint operator/(Wint a,const Wint &b)
{
return a/=b;
}
Wint& operator%=(Wint &a,const Wint &b)
{
return a-=a/b*b;
}
Wint operator%(Wint a,const Wint &b)
{
return a%=b;
}
bool cmp(const Wint &a,ll c,int d,const Wint &b)
{
ll l=-(a.base<<1),t=0;
if(b.size()<a.size()+d&&c)return 1;
for(int i=b.size()-1; l<=t&&t<=0&&i>d; --i)
t=t*a.base+c*(i-d-1<a.size()?a[i-d-1]:0)-b[i];
for(int i=d-1; l<=t&&t<=0&&~i; --i)
t=t*a.base-b[i];
return t>0;
}
void sub(Wint &a,const Wint &b,ll k,int d)
{
int l=b.size()+d;
for(int i=d+1; i<=l; ++i)
{
ll tmp=a[i]-k*b[i-d-1];
if(tmp<0)
{
a[i+1]+=(tmp-a.base+1)/a.base;
a[i]=tmp-(tmp-a.base+1)/a.base*a.base;
}
else a[i]=tmp;
}
for(int i=l+1; i<a.size()&&a[i]<0; ++i)
{
a[i+1]+=(a[i]-a.base+1)/a.base;
a[i]-=(a[i]-a.base+1)/a.base*a.base;
}
a.trim(0);
}
Wint sqrt(Wint a)
{
Wint ret;
ret.assign((a.size()+1)>>1,0);
for(int i=ret.size()-1; ~i; --i)
{
int l=0,r=a.base,m=ret[i]=(l+r)>>1;
while(r-l>1)
{
if(cmp(ret,m,i-1,a))r=m;
else l=m;
m=ret[i]=(l+r)>>1;
}
sub(a,ret,m,i-1);
ret[i]+=m;
}
ret.trim(0);
for(int i=0; i<ret.size(); ++i)ret[i]>>=1;
return ret;
}
int check(Wint n)
{
Wint sn=sqrt(n);
return sn*sn==n||(sn-1)*(sn-1)==n||(sn+1)*(sn+1)==n;
}
int main()
{
int t;
for(cin>>t; t--;)
{
Wint n,m;
cin>>n,m=n*(n-1)/2;
int ans=check(n)*2+check(n*(n-1)/2);
cout<<(ans==0?"League of Legends\n":
ans==1?"Clash Royale\n":
ans==2?"Hearth Stone\n":
"Arena of Valor\n");
}
}
Transport Ship
拆成01背包。
#include<stdio.h>
#include<string.h>
const int N=511,S=32767>>1,M=1e9+7;
int t,n,q,m,v[N],f[N][S];
int main()
{
for(scanf("%d",&t); t--;)
{
scanf("%d%d",&n,&q);
for(int i=m=0,V,C; i<n; ++i)
{
scanf("%d%d",&V,&C);
for(int i=0; i<C; ++i)
v[++m]=(1<<i)*V;
}
for(int i=f[0][0]=1; i<=m; ++i)
for(int s=0; s<S; ++s)
if(f[i][s]=f[i-1][s],s>=v[i])
f[i][s]=(f[i][s]+f[i-1][s-v[i]])%M;
for(int i=0,s; i<q; ++i)
{
scanf("%d",&s);
printf("%d\n",f[m][s]);
}
}
}
Poor God Water
矩阵乘一下。
#include<cstdio>
#include<algorithm>
#define mul(a,b,c) (1LL*(a)*(b)%(c))
using namespace std;
typedef long long ll;
const ll N=9,M=1e9+7;
struct Matrix
{
static int n;
ll a[N][N];
Matrix(ll k=0)
{
for(int i=0; i<n; ++i)fill(a[i],a[i]+n,0),a[i][i]=k;
}
ll* operator[](int n)
{
return a[n];
}
};
int Matrix::n=N;
Matrix operator*(const Matrix &a,const Matrix &b)
{
Matrix r(0);
for(int i=0; i<r.n; ++i)
for(int j=0; j<r.n; ++j)
for(int k=0; k<r.n; ++k)
r.a[i][j]=(r.a[i][j]+mul(a.a[i][k],b.a[k][j],M))%M;
return r;
}
Matrix pow(Matrix a,ll b)
{
Matrix r(1);
for(; b; b>>=1,a=a*a)
if(b&1)r=r*a;
return r;
}
int main()
{
ll t,n,ans;
for(scanf("%lld",&t); t--;)
{
scanf("%lld",&n);
if(n<3)
{
printf("%d\n",n==1?3:9);
continue;
}
Matrix A,P;
for(int i=0; i<N; ++i)A[i][0]=1;
P[0][3]=P[0][6]=1;
P[1][0]=P[1][3]=P[1][6]=1;
P[2][0]=P[2][3]=1;
P[3][1]=P[3][4]=P[3][7]=1;
P[4][1]=P[4][7]=1;
P[5][1]=P[5][4]=1;
P[6][5]=P[6][8]=1;
P[7][2]=P[7][8]=1;
P[8][2]=P[8][5]=1;
A=pow(P,n-2)*A;
for(int i=ans=0; i<N; ++i)ans=(ans+A[i][0])%M;
printf("%lld\n",ans);
}
}