题目描述
小蓝有一个 01 串 s=s1s2s3…sn。
以后每个时刻,小蓝要对这个 01 串进行一次变换。每次变换的规则相同。对于 01 串 s=s1s2s3…sn,变换后的 01 串s'=s′_1 s′_2 s′_3 ……s′_n 为:
s'1=s1;
s'i=si−1⊕si。
其中 a⊕b=表示两个二进制的异或,当a和 b相同时结果为 0,当 a和b不同时结果为 1。
请问,经过 t次变换后的 01 串是什么?
输入
输入的第一行包含两个整数 n,t,分别表示 01 串的长度和变换的次数。
第二行包含一个长度为 n的 01 串。
输出
输出一行包含一个 01 串,为变换后的串。
样例输入
5 3
10110
样例输出
11010
题目分析
【样例说明】
初始时为 10110,变换 1 次后变为 11101,变换 2 次后变为10011,变换 3次后变为 11010。
【评测用例规模与约定】
对于所有评测用例,1≤n≤10000=, 1≤t≤10^18。
数据规模太大了怎么办,找循环节啊!
异或太难怎么办,重载运算符啊!
TLM怎么办,推到所有结论,开始递推!
就是感觉^重载的挺好的,写下来记录一下。
失败代码
//STL好慢啊
//装逼失败
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+10;
ll n,k;
string s,t,temp;
string operator ^ (string s,string t) {
string st;
if(s.size()<t.size())
swap(s,t);
if(s.size()!=t.size())
st=s.substr(0,(int) s.size()-t.size()),
s=s.substr((int) s.size()-t.size());
for(int i=0; i<s.size(); i++)
st+=(s[i]==t[i])?"0":"1";
return st;
}
int main() {
cin>>n>>k>>s;
temp=s;
if(n==1) {
cout<<s;
return 0;
}
int cnt=0;
t=s.substr(0,n-1);
s=s^t;
while(1) {
cnt++;
if(s==temp||cnt==k)
break;
t=s.substr(0,n-1);
s=s^t;
}
if(cnt<k) {
k%=cnt;
while(k--) {
t=s.substr(0,n-1);
s=s^t;
}
}
cout<<s;
return 0;
}
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int n;
long long t;
int a[N],b[N],c[N];
bool check() {
for(int i=1; i<=n; i++)
if(a[i]!=c[i])
return false;
return true;
}
char str[N];
int main() {
cin>>n>>t;
for(int i=1; i<=n; i++)
cin>>str[i];
for(int i=1; i<=n; i++) {
a[i]=str[i]-'0';
b[i]=a[i];
}
if(n==1) {
cout<<a[1]<<endl;
return 0;
}
int cnt=1;
c[1]=b[1];
for(int i=2; i<=n; i++)
c[i]=b[i]^b[i-1];
for(int i=1; i<=n; i++)
b[i]=c[i];
while(1) {
if(check())
break;
for(int i=2; i<=n; i++)
c[i]=b[i]^b[i-1];
for(int i=1; i<=n; i++)
b[i]=c[i];
cnt++;
}
t=t%cnt;
for(int i=1; i<=n; i++)
b[i]=a[i];
for(int i=1; i<=t; i++) {
for(int j=n; j>=2; j--)
a[j]^=a[j-1];
}
for(int i=1; i<=n; i++)
cout<<a[i];
return 0;
}