Chinese Rings 2842 hdu (http://qzc.zgz.cn/Y-jiulianhuan3.htm 很流氓的网址)
2010-03-27 17:30
495 查看
]/* http://qzc.zgz.cn/Y-jiulianhuan3.htm 原来这是一个游戏 记从始点到前k个环在上用f(k)步,考虑怎么上这前k个环呢?可以先上前k-1个环,用f(k-1)步, 再下前k-2个环,用f(k-2)步。此时仅有第k-1个环在上,可以进行动作Q上k号环,用1步, 然后再上前k-2个环,用f(k-2)步。f(k)就是以上各个动作所需步数的和, f(k)=f(k-1)+f(k-2)+1+f(k-2) =f(k-1)+2f(k-2)+1即 f(k) =f(k-1)+2f(k-2)+1 这是确定函数关系的一种方法,叫做递归方法,与大家熟知的数学归纳法的原理有相似之处。 如果知道了f(1),f(2)的值,由此可以计算出f(3),有了f(3),与f(2)一起又可以计算f(4),等等, 直到f(9),或者更一般的f(k)。当然,这必须先知道f(1),f(2)的值,这犹如数学归纳法里的归纳假设。 容易知道,f(1)=1,f(2)=2。所以由 f(k) =f(k-1)+2f(k-2)+1,f(1)=1,f(2)=2 */ #include <iostream> #include <cstdio> using namespace std; const int mod = 200907; struct Mat { long long int num[3][3]; Mat() { for(int i = 0; i < 3; i++) for(int j = 0; j < 3; j++) num[i][j] = 0; } }; Mat mal(Mat a, Mat b) { Mat r; for(int i = 0; i < 3; i++) for(int k = 0; k < 3; k++) { if(a.num[i][k]) for(int j = 0; j < 3; j++) { if(b.num[k][j]) r.num[i][j] = (r.num[i][j] + a.num[i][k] * b.num[k][j]) % mod; } } return r; } Mat mul(Mat a, Mat b, int n) { while(n) { if(n & 1) { b = mal(a, b); n--; } else { a = mal(a, a); n >>= 1; } } return b; } int main() { int n; while( cin >> n && n) { if(n == 1 || n == 2) { printf("%d/n", n); continue; } Mat init, unit; init.num[0][0] = 1; init.num[0][1] = 2; init.num[0][2] = 1; init.num[1][0] = 1; init.num[2][2] = 1; unit.num[0][0] =2; unit.num[1][0] = 1; unit.num[2][0] = 1; Mat ans = mul(init, unit, n - 2); printf("%I64d/n", ans.num[0][0] % mod); } }http://acm.hdu.edu.cn/showproblem.php?pid=2842
//递推公式 f
= f[n-1] + 2*f[n-2] +1 f[1] = 1 f[2] =2
#include<iostream>//2255440 2010-03-27 17:26:15 Accepted 2842 0MS 296K 1332 B C++ 悔惜晟
using namespace std;
const int mod = 200907;
struct stu
{
long long int a[3][3];
} df1, df2;
stu mul(stu p, stu q)
{
int i, j, k;
stu r;
for(i = 0; i < 3; i++)
for(j = 0; j < 3 ; j++)//一开始这里括号加错了,郁闷了好久
{
r.a[i][j] = 0;
for( k = 0; k < 3; k++)
r.a[i][j] += p.a[i][k]* q.a[k][j];
if(r.a[i][j] >= mod)
r.a[i][j] %= mod;
}
return r;
}
stu mal(int n)
{
stu p = df1;
stu q = df2;
while(n > 1)
{
if(n % 2 == 0)
{
q = mul(q, q);
n /= 2;
}
else
{
p = mul(p , q);
n--;
}
}
return mul(p, q);
}
int main()
{
int n, s[4], i, j;
long long sum;
while(cin>>n && n != 0)//0的时候不执行
{
if(n == 1)
cout<<"1"<<endl;
else if(n == 2)
cout<<"2"<<endl;
else
{
n -= 2;
for(i = 0 ;i < 3; i++)
for(j =0 ; j <3 ;j++)
if(i == j)
df1.a[i][j] = 1;
else
df1.a[i][j] =0;
df2.a[0][0] = 1;
df2.a[0][1] = 2;
df2.a[0][2] = 1;
df2.a[1][0] = 1;
df2.a[1][1] = 0;
df2.a[1][2] = 0;
df2.a[2][0] = 0;
df2.a[2][1] = 0;//一开始矩阵写错了。纠结啊。。
df2.a[2][2] = 1;//
s[0] = 2;
s[1] = 1;
s[2] = 1;
stu ans;
ans = mal(n);
sum = 0;
for(i = 0 ; i < 3; i++)
sum += (ans.a[0][i]*s[i])%mod;
cout<<sum%mod<<endl;
}
}
}
相关文章推荐
- http://acm.hdu.edu.cn/showproblem.php?pid=2842
- http://acm.hdu.edu.cn/showproblem.php?pid=3549&&ISAP
- http://acm.hdu.edu.cn/showproblem.php?pid=2066&&多源多点
- http://acm.hdu.edu.cn/showproblem.php?pid=1102
- http://acm.hdu.edu.cn/showproblem.php?pid=1162
- Max Sum http://acm.hdu.edu.cn/showproblem.php?pid=1003
- http://acm.hdu.edu.cn/showproblem.php?pid=2925
- http://acm.hdu.edu.cn/showproblem.php?pid=2795&&线段树之求最小区间端点值
- http://acm.hdu.edu.cn/showproblem.php?pid=1333
- http://acm.hdu.edu.cn/showproblem.php?pid=2303 (素数打表 + java大数取模)
- http://acm.hdu.edu.cn/showproblem.php?pid=3521 (暴力)
- http://acm.hdu.edu.cn/showproblem.php?pid=1698 成段更新,总区间求和
- http://acm.hdu.edu.cn/showproblem.php?pid=2094
- HDU1973 http://acm.hdu.edu.cn/showproblem.php?pid=1973
- http://acm.hdu.edu.cn/showproblem.php?pid=2227 dp + 线段树
- http://acm.hdu.edu.cn/showproblem.php?pid=2688 数状数组 线段树
- http://acm.hdu.edu.cn/showproblem.php?pid=1874 简单题
- http://acm.hdu.edu.cn/showproblem.php?pid=1142
- ACM 错误提示-Online Judge F.A.Q.(Chinese)---http://acm.nankai.edu.cn
- http://acm.hdu.edu.cn/showproblem.php?pid=1020..