【hdoj 1005】有限状态机

题目:传送门

解答:f(1) = 1, f(2) = 1, f(n) = (A * f(n – 1) + B * f(n – 2)) mod 7

乍看之下像是递归。但是数据范围太大了,一定会超时。可以想到找规律。

如果将 f(n) 视为一个状态,那么决定它的是谁?是前两个状态。而且因为 mod 7,所以这个函数的定义域、值域都是{0,1,2,3,4,5,6}。

这样,,我们可以构造一个 7*7的有限状态机(二维数组),每个状态填写出现的次数。当我们即将填写一个状态时发现里面已经出现了次数,当前次数 – 已有次数就是循环的规模。最多计算49次,我们一定会发现循环规律。

这里需要注意的是:

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#include<iostream>#include<vector>#include<map>using namespace std;int main(){int a, b, i, j;long n;int map[7][7];while (cin>>a>>b>>n && a && b && n){if(n == 1 || n == 2){cout<<"1"<<endl;continue;}memset(map, 0, sizeof(map));int val = 1;map[1][1] = val;i = 1;j = (a*1 + b*1) % 7;int k = 0;while(!map[i][j]){val++;map[i][j] = val;int tmp = j;j = (a*j + b*i) % 7;i = tmp;// 多余操作,状态机一定会停机//num–;//if (num == 0)//{// cout<<j<<endl;// break;//}}int circle = (val + 1) – map[i][j];int start = map[i][j];n = (n – (start – 1)) % circle;;if(n == 0) n = circle;n = n + (start – 1);int ans;for (int k = 0; k < 7; k++){for (int l = 0; l < 7; l++){if (n == map[k][l]){ans = k;}}}cout<<ans<<endl;continue;}return 0;}

还深深埋在心底,要除去,怕是不能活命。

【hdoj 1005】有限状态机

相关文章:

你感兴趣的文章:

标签云: