题目大意:题目大意给定一系列灯的初始状态,0代表暗,1代表亮,每一秒所有的灯都有可能发生状态切换,

切换规则:当前灯的左边第一个灯是亮的,则当前的灯切换状态,如果当前灯的左边第一盏灯是暗的,则当前灯的状态无需变化!

注意:最左边的参考左右边那栈灯。

题目分析;

首先有两种情况:

左边第一盏灯亮的:

                              当前灯的动作:     1->0;    0->1;

左边第一盏灯暗的:

                               当前灯的动作:

                                                    1->1;      0->0;

我们可以看到的是, 可以用一个方程来模拟这个过程: F[i] = ( f [ i] +f [i+n-2]%n+1 )%2;

所以我们只要计算这个值就OK啦。

然后由于数据过大,开数组肯定会爆掉~

这里我们要想到的是 矩阵是一个模拟递归的高效算法

这里我们要构造一个 可以计算如上的方程的矩阵:

              1 0 0...0 1

              1 1 0...0 0

              0 1 1..0 0

              0 0 1..0 0

               . . . 0 ....

               . . .0.....

               0 0 0..0 1

代码:


#include <iostream>  
#include <cstdio>  
#include <cstring>  
using namespace std;  
const int N = 105;  
const int mod = 2;  
struct Mat  
{  
    int num[N][N];  
    Mat()  
    {  
        for(int i = 0; i < N; i++)  
        for(int j = 0; j < N; j++)  
            num[i][j] = 0;  
    }  
};  
Mat mul(Mat a, Mat b, int n)  
{  
    Mat r;  
    for(int i = 0; i < n; i++)  
    for(int k = 0; k < n; k++)  
    {  
        if(a.num[i][k] == 0)  
            continue;  
        for(int j = 0; j < n; j++)  
        {  
            if(b.num[k][j] == 0)  
                continue;  
            r.num[i][j] = (r.num[i][j] + a.num[i][k] * b.num[k][j]) % mod;  
        }  
    }  
    return r;  
}  
Mat mal(Mat init, Mat unit, int m, int n)  
{  
    while(m)  
    {  
        if(m & 1)  
        {  
            unit = mul(init, unit, n);  
            m--;  
        }  
        else
        {  
            init = mul(init, init, n);  
            m >>= 1;  
        }  
    }  
    return unit;  
}  
int main()  
{  
    int m;  
    while(cin >> m)  
    {  
        char str[N];  
        cin >> str;  
        Mat init, unit;  
        int len = strlen(str);  
        for(int i = 0; i < len; i++)  
        {  
            unit.num[i][0] = str[i] - '0';  
        }  
        init.num[0][0] = 1; init.num[0][len - 1] = 1;  
        int k = 0;  
        for(i = 1; i < len; i++)  
        {  
            for(int j = k; j < k + 2; j++)  
                init.num[i][j] = 1;  
            k++;  
            if(k == len - 1)  
                break;  
        }  
        Mat ans;  
        ans = mal(init, unit, m, len);  
        for(i = 0 ; i < len; i++)  
            cout << ans.num[i][0];  
        cout << endl;  
    }  
}

死也想不明白下面这个代码为什么就TLE了。。
/*#include <iostream>
#include <algorithm>
#include <string>
char str[102];
using namespace std;
struct mat
{
 int map[101][101];
};
mat unit,res,temp;
int t,n;
mat mul(mat a,mat b)
{
 mat c;
 for(int i=1;i<=n;i++) 
  for(int j=1;j<=n;j++)
  {
  // if(a.map[i][j]==0)continue;
   c.map[i][j]=0;
   for(int k=1;k<=n;k++)
   {
  //  if(b.map[j][k]==0)continue;
    c.map[i][j]=(c.map[i][j]+(a.map[i][k]*b.map[k][j])%2)%2;
   }
  }
  return c;
}
void TOW()
{
 mat ans=unit;
 mat bns=temp;
 while(t)
 {
  if(t%2==1)
  {
   t--;
   ans=mul(ans,bns);
  }
  else
  {
  bns=mul(bns,bns);
  t=t/2;
  }
 }
 res=mul(res,ans);
}
int main()
{
 int len;
 memset(unit.map,0,sizeof(unit.map));
 for(int i=1;i<=100;i++)
  unit.map[i][i]=1;
 while(scanf("%d",&t)!=EOF)
 {
  memset(res.map,0,sizeof(res.map));
  memset(temp.map,0,sizeof(temp.map));
  scanf("%s",&str);
  len=strlen(str);
  n=len;
  for(i=1;i<=len;i++)
   res.map[1][i]=str[len-i]-'0';
  for(i=1;i<=n;i++)
  {
   if(i!=n)
    temp.map[i][i]=temp.map[i+1][i]=1;
   else
    temp.map[1][n]=temp.map[n][n]=1;
  }
  TOW();
  for(i=n;i>=1;i--)
   printf("%d",res.map[1][i]);
  printf("\n");
 }
 return 0;
}*/

posted on 2011-08-10 17:13  →木头←  阅读(445)  评论(0编辑  收藏  举报