Topcoder SRM 566 countJourneys

本文介绍了一种使用动态规划和矩阵快速幂解决企鹅旅行问题的方法。在一个环形地图上,企鹅每天可以向左右移动特定步数,目标是计算在指定天数后返回起点的不同路径数量。通过优化算法来应对大规模数据输入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设一个环形地图,上面有numCities个城市,一个企鹅在城市间移动,第k天可以往左或往右移动k步。给定daysPassed天时间,问在daysPassed天后回到起点的方法有多少? Problem Statement

可以用动态规划,记录每一次移动后在每一个位置的方法数。但这里因为daysPassed的取值可以到10^18,所以不能直接枚举每一天。因为每一天的实际移动是(k%numCities),所以其实移动的模式在经过numCities天后会重复出现,利用这点可以采用二分。

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include "string.h"

using namespace std;

class PenguinEmperor {
public:
	int countJourneys(int, long long);
};

const long long M = 1000000007;
vector<long long> Mul(vector<long long> a, vector<long long> b){
	int n=a.size();
	vector<long long> c(n,0);
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			int next=(i+j)%n;
			c[next]+=a[i]*b[j];
			c[next]%=M;
		}
	}
	return c;
}
vector<long long> Pow(vector<long long> a, long long n){
	if(n==0){
		a=vector<long long>(a.size(),0);
		a[0]=1;
		return a;
	}
	if(n%2==0)
		return Pow(Mul(a,a),n/2);
	else
		return Mul(a,Pow(a,n-1));
}
int PenguinEmperor::countJourneys(int numCities, long long daysPassed) {
	vector<long long> period(numCities,0),extra(numCities,0);
	period[0]=extra[0]=1;
	for(int i=1;i<numCities;i++){
		vector<long long> move(numCities,0);
		move[i]=move[numCities-i]=1;
		period=Mul(period,move);
		if(i<=(daysPassed%numCities))
			extra=Mul(extra,move);
	}
	vector<long long> res=Mul(extra,Pow(period,daysPassed/(long long)numCities));
	return (int)(res[0]%M);
}

<%:testing-code%>

//Author@logicnut

//Powered by KawigiEdit 2.1.4 (beta) modified by pivanof!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值