列表

详情


NC20909. 游戏

描述

有 n 个人围成一个环玩传球游戏,每轮游戏手里拿着球的那个人必须将球传给他(她)的一个朋友。游戏一共进行了 m 轮,初始球在第 a 个人手中,问游戏结束后球在第 b 个人手中的方案数。
多组测试数据。答案对 109+7 取模。

输入描述

第一行三个整数 Q,n,m(1≤ Q≤105,n≤200,m≤109),含义如题目所示。
接下来 n 行,每行 n 个整数表示每个人的朋友关系,若第 i 行的第 j 个数为 0 表示 i 与 j 不是朋友,反之亦然。请特别注意本题中朋友关系是有向的。特别地,一个人不能为自己的朋友。
接下来 Q 行,每行两个整数 a,b 分别表示一组询问。

输出描述

输出共 Q 行,每行一个整数,表示答案。

示例1

输入:

1 2 1
0 1
1 0
1 1

输出:

0

说明:

测试数据中共有两个人玩游戏。包含一组询问。
第一个人与第二个人互为朋友。游戏共进行了一轮。
第一次询问中询问游戏结束后第一个人手中仍然有球的方案数。
显然在一轮游戏后,由于每轮传球一个人必须将球传给他(她)的朋友,所以球不可能还在自己手里。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 97ms, 内存消耗: 2668K, 提交时间: 2018-12-22 21:29:14

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 205;
const LL mod = 1e9+7;
LL m=0,n=0; 
struct Matrix{
  LL a[N][N];
  Matrix(){
    memset(a,0,sizeof(a));
  }
  void init(){
    for(int i=1;i<=n;++i)a[i][i]=1;
  }
  Matrix operator *(const Matrix &rhs)const{
     Matrix ret;
     for(int i=1;i<=n;++i)
      for(int j=1;j<=n;++j)
        for(int k=1;k<=n;++k)
          ret.a[i][j]=(ret.a[i][j]+a[i][k]*rhs.a[k][j]%mod)%mod;
      return ret;
  }
  Matrix operator ^(LL mi)const{
    Matrix tmp=(*this),ret;
    ret.init();
    while(mi){
      if(mi&1)ret=ret*tmp;
      tmp=tmp*tmp;
      mi>>=1;
    }
    return ret;
  }
};
int main(){
	int q=0;
	scanf("%d%lld%lld",&q,&n,&m);
	Matrix mk;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%lld",&(mk.a[i][j]));
		}
	}
	Matrix ans=mk^(m);
	while(q--){
		int a1=0,b1=0;scanf("%d%d",&a1,&b1);
		printf("%lld\n",ans.a[a1][b1]);
	}
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 207ms, 内存消耗: 2284K, 提交时间: 2020-03-15 13:18:10

#include<bits/stdc++.h>
using namespace std;
int x,y,n,m,Q,M=1e9+7;
struct h
{
	long long R[205][205];
	h()
	{
		memset(R,0,sizeof(R));
	}
	h operator *(const h &a)
	{
		h s;
		for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		s.R[i][j]=(s.R[i][j]+R[i][k]*a.R[k][j])%M;
		return s;
	}
}a,s;
int main()
{
	scanf("%d%d%d",&Q,&n,&m);
	for(int i=1;i<=n;i++)
	{
		s.R[i][i]=1;
		for(int j=1;j<=n;j++) scanf("%d",&a.R[i][j]);
	}
	for(;m;a=a*a,m>>=1) 
	if(m&1)
	s=s*a;
	while(Q--)
	{
		scanf("%d%d",&x,&y);
		printf("%d\n",s.R[x][y]);
	}
	return 0;
}

上一题