第一次做CF上面的题目,感觉跟平常做的题目有一点不同,抽象的问题很多,需要优秀的数学逻辑将其转化为我们见过的算法模型。
CF比赛连接 http://codeforces.com/contest/227
一小时做了两个水题,然后就卡在了C题上,等比赛结束之后我看了人家的代码,提取出几组数据,一对比才发现,原来我最前面有一个数字计算错误,导致了公式无法推出。。。。。。真是不细心,
不然估计这个题目应该也能提交
CF比赛连接 http://codeforces.com/contest/227
一小时做了两个水题,然后就卡在了C题上,等比赛结束之后我看了人家的代码,提取出几组数据,一对比才发现,原来我最前面有一个数字计算错误,导致了公式无法推出。。。。。。真是不细心,
![快哭了](http://static.blog.csdn.net/xheditor/xheditor_emot/default/fastcry.gif)
A题就 一次给出三个点,然后求第三个点是在前两个点的左边右边还是正前面(正前面是三点一线的情况),左边右边一律成90度夹角。
B题就 给一个很长的数列,两种查找方式,一个是从前往后,另一个是从后往前,要求输出给定查找值对于这两种查找方式的查找比较次数(一共两个数字),其实算出一个另一个就出来了。
C题就 三个房子(a、b、c),在a房子中有很多很多外星人,外星人按次序编号,要求将外星人全部移动到c房子中,条件是:每次只能移动一个外星人,移动一次花费一分钟,每次移动只能在相邻的房子中进行,当且仅当这两个房子(外星人从一个出进另外一个)中,只有编号是最大的外形人才能移动。问最少的移动时间是多少。结果对给定值取余。其实这个题目跟汉诺塔极其类似,因此它一定存在一个简单的通项公式,并且是指数型的。我们通过计算得知,当只有一个外星人时 最少时间为2 即a[1]=2 ,a[2]=8,a[3]=26,a[4]=80猜测递推公式为 a[n] = a[n-1]*3 + 2;然后通过待定系数法计算出通项公式 a[n] = (3^n) - 1 {a>1}; a[1] = 2;然后再用快速幂取余(又是模板)求解即可。
// problem URL : codeforces.com/contest/227/problem/C
// Codeforces Round #140 (Div. 2) -- C
// 一个类似于汉诺塔的题目,可以推出通项公式,然后利用快速幂取模进行求解
// 公式 an = 3*a(n-1) - 1
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
long long PowerRemainder(int a,int p,int n){ // quick calculate (a ^ p ) % n
if (p == 1){return a % n;}
if (p == 0){return 0;}
long long r = PowerRemainder(a,p>>1,n);
return (p & 1)?((r * (a%n)) % n * r % n):(r * r % n);
}
int main()
{
int n,m;
while(cin >> n >> m){
int res = PowerRemainder( 3 , n , m ) - 1;
cout << ( (~res)?(res):(m - 1) ) << endl;
}
return 0;
}