SRM541

550
AkariDaisuki
题意:f(X) = Waai + X + Akari + X + Daisuki,求F在f^k(S)种出现的次数,k<=10^10,S,F,A,B,C串长<=50

分析:显然F出现次数的增量之和X的前后缀有关,因此当到达一定次数之后X的前后缀就不会发生变化了,只要矩阵算算就可以了,次数较少的时候可以暴力

1000
XorLife
题意:一个无限大的平面,初始除了一个50*50的矩阵之外全部是0,每次每个格子=周围四个格子的数异或和再异或这个格子的数,问k次操作之后有多少个格子是1; k109

分析:首先,这个过程具有叠加性,可以把最后的结果看成初始若干个1作用k步叠加而成;对一个1产生的效果模拟两步,发现两步之后只会影响奇偶性与初始1位置相同的格子,意味着假如两步两步走,会把平面根据奇偶性分成互不相关的两部分;因此我们可以根据整个图记忆化搜索(我是map了一个vector),状态很少

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef vector<string> vs;
typedef pairint> pi;
typedef long long LL;
int di[5][2]={{1,0},{0,1},{-1,0},{0,-1},{0,0}};
class XorLife {
    public:
    mapMp;
    vs trans(vs from){
        string tmp;
    tmp.assign(2+from[0].size(),'.');
    vs ret;
    ret.assign(2+from.size(),tmp);
    int n=ret.size(),m=ret[0].size();
    for(int i=0;ifor(int j=0;jint cnt=0;
            for(int d=0;d<5;d++){
                int ni=i+di[d][0],nj=j+di[d][1];
                if(ni>0&&ni1&&nj>0&&nj1&&from[ni-1][nj-1]=='o')cnt++;
            }
            if(cnt&1)ret[i][j]='o';
        }
    }
    return ret;
    }    
    long long countAliveCells(vector<string> field, int K) {
    if(!field.size())return 0;
    if(K&1)field=trans(field),K--;
//  printf("K=%d\n",K);
//  for(int i=0;i
    if(Mp.find(pi(field,K))!=Mp.end())return Mp[pi(field,K)];
    if(!K){
        LL ret=0;
        for(int i=0;ifor(int j=0;j0].size();j++){
                ret+=field[i][j]=='o';
            }
        }
        Mp[pi(field,K)]=ret;
        return ret;
    }
    vector<string>nxt[2][2];
    int n=field.size(),m=field[0].size();
    for(int i=0;ifor(int j=0;j1][j&1];
            if(ob.size()<=i/2)ob.push_back(string(""));
            ob.back().push_back(field[i][j]);
        }
    }
    LL ret=0;
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++)
            ret+=countAliveCells(nxt[i][j],K>>1);
    }
    Mp[pi(field,K)]=ret;
    return ret;
        return 0;
    }
};

你可能感兴趣的:(srm)