可乐
第一眼以为和概率期望什么的有关系,吓得不轻(我对那个东西有生理厌恶的),如果再来一个迷失游乐园之类的那就不好了。
不过定睛一看,蓝题。应该还好。朴素的想就是一个奇怪的分层图。然后玄学吸几口 \(O_2\) 就可以水过去。顺便提一下,由于脑残了,边数开的不是太大,忽略了有额外边的存在,调了好久【汗颜】……
#include<cstdio>
//#define zczc
const int N=1000010;
const int M=31;
const int mod=2017;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar(); }
wh*=f;return;
}
int m,n,want;
struct edge{
int t,next;
}e[310];
int esum,head[M];
inline void add(int fr,int to){
esum++;
e[esum].t=to;
e[esum].next=head[fr];
head[fr]=esum;
return;
}
inline void Add(int &s1,int s2){
s1+=s2;if(s1>=mod)s1-=mod;return;
}
int f[N][M];
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
int s1,s2;
read(m);read(n);
for(int i=1;i<=n;i++){
read(s1);read(s2);
add(s1,s2);add(s2,s1);
}
for(int i=0;i<=m;i++){
add(i,i);
if(i^0)add(i,0);
}
read(want);
f[0][1]=1;
for(int i=0;i<want;i++){
for(int wh=0;wh<=m;wh++){
for(int j=head[wh];j;j=e[j].next){
Add(f[i+1][e[j].t],f[i][wh]);
}
}
}
int ans=0;
for(int i=0;i<=m;i++)Add(ans,f[want][i]);
printf("%d\n",ans);
return 0;
}
但做人不能如此不道德,勾引评测姬以换取 \(AC\) 的行为是极其不正当的。
题目标签以及题解区里有矩阵乘法的影子,那就看一下吧。
上面那个算法慢在哪里,慢就慢在中间那个三重循环。假如我们把每一个f[i]当成一个1\(\times ?\) 的矩阵,那么我们需要做的就是快速地从一个矩阵转向另一个矩阵,得到答案。想到用矩阵乘法。然后推导结论,快速幂即可。
#include<cstdio>
//#define zczc
const int N=1000010;
const int M=31;
const int mod=2017;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar(); }
wh*=f;return;
}
int m,n,want;
struct node{
int l1,l2,a[M][M];
}newone;
inline void add(int &s1,int s2){
s1+=s2;s1%=mod;return;
}
inline node operator *(node s1,node s2){
node an=newone;
an.l1=s1.l1,an.l2=s2.l2;
for(int i=0;i<=an.l1;i++){
for(int j=0;j<=an.l2;j++){
for(int k=0;k<=an.l2;k++){
add(an.a[i][j],s1.a[i][k]*s2.a[k][j]);
}
}
}
return an;
}
inline node pow(node s1,int s2){
if(s2==1)return s1;
node an=pow(s1,s2>>1);
if(s2&1)return an*an*s1;
else return an*an;
}
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
int s1,s2;
node s=newone;
read(m);read(n);
s.l1=s.l2=m;
for(int i=1;i<=n;i++){
read(s1);read(s2);
s.a[s1][s2]=s.a[s2][s1]=1;
}
for(int i=0;i<=m;i++){
s.a[i][0]=1;
if(i^0)s.a[i][i]=1;
}
read(want);
node an=pow(s,want);
int ans=0;
for(int i=0;i<=m;i++)add(ans,an.a[1][i]);
printf("%d\n",ans);
return 0;
}