您的位置:首页 > 编程语言 > C语言/C++

MZ test17# NOIP模拟题 # T4 第4题 路线统计(route.cpp/pas)[key:矩阵]

2016-05-17 20:32 423 查看
第4题 路线统计(route.cpp/pas)

【问题描述】

给出一个n个点有向图,求从s点到f点恰好经过时间t的路径总数。不能在某个点停留,可以重复的走各点。

【输入数据】

第一行包含一个整数n, 所有点是从0到n-1编号.

接下来n行,每行包含n个字符. 第i行第j个字符表示i到j需要的时间,字符只可能是’1’到’5’, 或者是’.’表示i不能到达j, 保证主对角线都是’.’。

接下来一行3个整数s, f, t。

【输出数据】

输出总方案数mod 502630的值。

【样例输入】route.in

3

.12

2.1

12.

0 2 5

【样例输出】route.out

8

【数据范围及提示】

对于20%的数据, 输入的字符不是’1’就是’.’;

对于100%的数据, 1 <= n <= 10; 1 <= s,f <= n; 1 <= t <= 10^9

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int MOD=502630;
struct matrix
{
int f[55][55];
void clear()
{
memset(f,0,sizeof(f));
}
}st,ans,E;

int n;
char s[15];
void readdata()
{
st.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
for(int j=1;j<=n;j++)
{
if(s[j-1]!='.')
{
int ret=s[j-1]-'0';
for(int k=1;k<ret;k++)
{
st.f[(k-1)*n+i][k*n+i]=1;
}
st.f[(ret-1)*n+i][j]=1;
}
}
}

n*=5;
E.clear();
for(int i=1;i<=n;i++)E.f[i][i]=1;
}

matrix o_o(matrix a,matrix b)
{
matrix c;
c.clear();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
{
c.f[i][j]=(c.f[i][j]+((long long)a.f[i][k]*b.f[k][j])%MOD)%MOD;
}
return c;
}

matrix mult(matrix a,int t)
{
matrix c=E;
while(t)
{
if(t%2)c=o_o(c,a);
t>>=1;
a=o_o(a,a);
}
return c;
}

void work()
{
int start,finish,t;
scanf("%d%d%d",&start,&finish,&t);
start++;finish++;
matrix ans=mult(st,t);
printf("%d\n",ans.f[start][finish]);
}

int main()
{
freopen("route.in","r",stdin);
freopen("route.out","w",stdout);
readdata();
work();
return 0;
}


附glk's code.

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int mod = 502630;
#define LL long long
struct Mat{
int A[300][300];
int h,l;
Mat() {memset(A,0,sizeof(A));h = l = 0;}
Mat operator * (const Mat& B)const{
Mat C;
C.h = h;C.l = B.l;
for(int i = 1;i <= h;++i)
for(int j = 1;j <= B.l;++j){
int tmp = 0;
for(int k = 1;k <= l;++k)
tmp = (tmp + ((LL)A[i][k] * B.A[k][j])%mod)%mod;
C.A[i][j] = tmp;
}
return C;
}
};

char Can[15][15];

Mat Pow(Mat B,int n){
Mat ans = B;
for(int i = 1;i <= B.h;++i)
for(int j = 1;j <= B.l;++j)
ans.A[i][j] = (i==j);
while(n){
if(n&1) ans = ans * B;
B = B * B;
n>>=1;
}
return ans;
}

int main(){
freopen("route.in","r",stdin);
freopen("route.out","w",stdout);
//A*A为t=2,A^k means  t = k + 1
//ans = A^(t-1)[s,f]
int n,tot,s,f,t;
scanf("%d",&n);
for(int i = 1;i <= n;++i)scanf("%s",Can[i]+1);
tot = n;
scanf("%d%d%d",&s,&f,&t);
++s,++f;
Mat B;
#define CC B.A
for(int i = 1;i <= n;++i){
for(int j = 1;j <= n;++j){
if(Can[i][j]=='.') continue;
int tmp = Can[i][j]-'0';
for(int k = 1;k < tmp;++k)
CC[(k-1)*n+i][k*n+i] = 1;
CC[(tmp-1)*n+i][j] = 1;
}
}
B.h = B.l = n * 5;
Mat ans = Pow(B,t);
printf("%d",ans.A[s][f]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: