HDU - 2276 Kiki & Little Kiki 2

Description

There are n lights in a circle numbered from 1 to n. The left of light 1 is light n, and the left of light k (1< k<= n) is the light k-1.At time of 0, some of them turn on, and others turn off.
Change the state of light i (if it's on, turn off it; if it is not on, turn on it) at t+1 second (t >= 0), if the left of light i is on !!!Given the initiation state, please find all lights’ state after M second. (2<= n <= 100, 1<= M<= 10^8)

 

Input

The input contains one or more data sets. The first line of each data set is an integer m indicate the time, the second line will be a string T, only contains '0' and '1' , and its length n will not exceed 100. It means all lights in the circle from 1 to n.
If the ith character of T is '1', it means the light i is on, otherwise the light is off.

 

Output

For each data set, output all lights' state at m seconds in one line. It only contains character '0' and '1.
 

Sample Input

    
    
1 0101111 10 100000001
 

Sample Output

  
  
1111000 001000010

题意:一排灯,给你初始状态,然后每秒都会有这样的操作:如果该盏灯的左边是亮的话,就改变状态,否则不变,最左边的参考最右边的

思路:很容易发现有:a1 = (a1+an)%2 , a2 = (a2 + a1) % 2 ......... an = (an + an-1)%2

   然后构造类似矩阵: 1 0 0 1   ,位运算快的多,因为这道题的特殊性

                                     1 1 0 0

                                     0 1 1 0

                                     0 0 1 1

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 105;
const int mod = 2;

int cnt;
struct Matrix {
	int v[maxn][maxn];
	Matrix() {}
	Matrix(int x) {
		init();
		for (int i = 0; i < maxn; i++) 
			v[i][i] = x;
	}
	void init() {
		memset(v, 0, sizeof(v));
	}
	Matrix operator *(Matrix const &b) const {
		Matrix c;
		c.init();
		for (int i = 0; i < cnt; i++)
			for (int j = 0; j < cnt; j++)
				for (int k = 0; k < cnt; k++)
					c.v[i][j] ^= (v[i][k] & b.v[k][j]);
		return c;
	}
	Matrix operator ^(int b) {
		Matrix a = *this, res(1);
		while (b) {
			if (b & 1)
				res = res * a;
			a = a * a;
			b >>= 1;
		}
		return res;
	}
} a, b, tmp;

int main() {
	int t;
	char str[maxn];
	int num[maxn];
	while (scanf("%d", &t) != EOF) {
		scanf("%s", str);	
		cnt = strlen(str);
		for (int i = 0; i < cnt; i++)
			num[i] = str[i] - '0';
		a.init();
		a.v[0][cnt-1] = a.v[0][0] = 1;
		for (int i = 1; i < cnt; i++)
			a.v[i][i] = a.v[i][i-1] = 1;
		tmp = a^t;
		int ans[maxn];
		memset(ans, 0, sizeof(ans));
		for (int i = 0; i < cnt; i++)
			if (num[i])
				for (int j = 0; j < cnt; j++)
					if (tmp.v[j][i])
						ans[j] = (ans[j]+ (tmp.v[j][i]*num[i])%mod) % mod;
		for (int i = 0; i < cnt; i++)
			printf("%d", ans[i]);
		printf("\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值