列表

详情


NC19772. 生命游戏

描述

明明和白白是好朋友,他们最近在研究 XOR 生命游戏。
在一个二维的平面中,细胞存在于一些格点上。每个时刻所有细胞都会同时分裂成四个,并分别移动到相邻的四个格点中;此时当某个格点上出现奇数个细胞的时候,只有一个能活下来;而当出现了偶数个细胞的时候,这个格点上的所有细胞同时消失。
明明明明明白白白不擅长数数,却偏要让白白算出从 1 到 N 时刻所有细胞的个数之和。无助的白白只好求助于聪明的你了。为了简化问题,数据保证初始时刻(时间戳为1)恰好有两个细胞。

输入描述

五个整数,N, x1, y1, x2, y2, 表示需要计算的时长为 N,两个细胞的坐标分别为 (x1, y1), (x2, y2).

输出描述

一个整数,表示 1 ~ N 时刻所有细胞个数之和。

示例1

输入:

3 0 0 2 2

输出:

14

说明:

第1个时刻的细胞有:(0, 0), (1, 1)
第2个时刻的细胞有:(0, 1), (1, 2), (3, 2), (-1, 0), (2, 1), (2, 3), (0, -1), (1, 0)
第3个时刻的细胞有:(2, 4), (0, -2), (4, 2), (-2, 0)
所以答案是 2 + 8 + 4 = 14

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 4ms, 内存消耗: 504K, 提交时间: 2019-10-11 23:40:44

#include <ctime>
#include <cstdio>
#include <algorithm>
#include <ctime>
#include <iostream>
#include <queue>
#include <bitset>
#include <string>
#include <cstring>
#include <set>
#include <cmath>
using namespace std;
namespace cell_xor_split{//一个细胞在屏幕上分裂向四周扩散,偶数个消失,奇数个保留,原位置不保留
    typedef __int128 ll;
    ll _one_cell_after_n_step(int n){//一个细胞在n秒后剩下个数
        ll ans = 1;
        while (n) {
            ans *= 4;
            n -= n & -n;
        }
        return ans;
    }
    inline short did(short x) {
        return x < 0 ? (x - 1) / 2: (x == 0 ? 0 : x  / 2);
    }
    ll _1D_hit_after_n_step(int x, int n) {//求单个维度下n步的冲突
        ll f[2][5] = {0};//0, 1为借位 2, 1, 2为不借位, 3, 4 为进位1, 2
        f[0][2] = 1;
        bool bz = 0, bz1 = 1;
        for (int bit = 1; bit < (1 << 30); bit <<= 1, swap(bz, bz1)) {
            memset(f[bz1], 0, sizeof(f[bz1] ));
            int v = ((n & bit) > 0) + 1;
            for (int i = -2; i <= 2; i ++){
                if (((i + 2) & 1) != ((x & bit) > 0)) continue;
                f[bz1][did(i) + 2] += f[bz][i + 2] * v;
            }
            if (v == 2) {
                for (int i = -2; i <= 2; i ++)
                    for (int j = -2; j <= 2; j += 4){
                        if (((i + j + 4) & 1) != ((x & bit) > 0)) continue;
                        f[bz1][did(i + j) + 2] += f[bz][i + 2];
                    }
            }
        }
        return f[bz][0 + 2];
    }
    ll _two_cell_hit_after_n_step(int x1, int y1, int x2, int y2, int n) {//两个细胞n秒撞在一起的部分
        x2 = abs(x2 - x1), y2 = abs(y2 - y1);
        int x = (x2 + y2) , y = (abs(x2 - y2)) ;//旋转45°,相当于切比雪夫变换
        return  _1D_hit_after_n_step(x, n) * _1D_hit_after_n_step(y, n);
    }
    ll _two_cell_after_n_step(int x1, int y1, int x2, int y2, int n) {//两个细胞相互作用后的结果
        return (_one_cell_after_n_step(n) - _two_cell_hit_after_n_step(x1, y1, x2, y2, n)) * 2;
    }
    ll _one_cell_after_0_n_step(int n){//一个细胞在n秒后剩下个数
        ll f[2][2] = {0};
        bool bz = 0, bz1 = 1;
        f[0][1] = 1;
        for (int i = 30; i >= 0 ;swap(bz, bz1), i --) {
            memset(f[bz1], 0, sizeof(f[bz1]));
            for (int j = 0; j < 2; j++) {
                int r = 1;
                if (j) r = ((n >> i) & 1);
                for (int k = 0; k <= r; k++)
                    f[bz1][(k == r) && j] += (f[bz][j] << (k << 1));
            }
        }
        return f[bz][1] + f[bz][0];
    }
    int ind(vector<int> d) {
        int x = 0;
        for (auto u:d)
            x = x * 5 + u + 2;
        return x;
    }
    void work(ll*fbz, ll*fbz1, bool n_bit, int bit,  vector<int>&d, int id, int wbz, int wbz1, ll v) {
        if (id == d.size()) {
            fbz1[wbz1] += fbz[wbz] * v;
            return;
        }
        int x = d[id];
        for (int i = -2; i <= 2; i ++) {
            if (((i + 2) & 1) != ((x & bit) > 0)) continue;
            work(fbz, fbz1, n_bit, bit, d, id + 1, wbz * 5 + i + 2, wbz1 * 5 + did(i) + 2, (v << n_bit));
        }
        if (n_bit) {
            for (int i = -2; i <= 2; i++)
                for (int j = -2; j <= 2; j += 4) {
                    if (((i + j + 4) & 1) != ((x & bit) > 0)) continue;
                    work(fbz, fbz1, n_bit, bit, d, id + 1, wbz * 5 + i + 2, wbz1 * 5 + did(i + j) + 2, v);
                //    f[bz1][sig1][did(i + j) + 2] += f[bz][sig][i + 2];
                }
        }
        /*for (int ix = -2; ix <= 2; ix++) {
            if (((ix + 2) & 1) != ((x & bit) > 0)) continue;
            for (int iy = -2; iy <=)
                f[bz1][sig1][did(ix) + 2] += f[bz][sig][ix + 2] * v;
        }
        if (v == 2) {

        }*/
    }
    ll _mD_hit_after_0_n_step(vector<int>&d, int n) {//求多个维度下0~n步的冲突
        ll f[2][2][100] = {0};//0, 1为借位 2, 1, 2为不借位, 3, 4 为进位1, 2
        vector<int>v(d.size(), 0);
        f[0][0][ind(v)] = 1;
        bool bz = 0, bz1 = 1;
        for (int bit = 1; bit < (1 << 30); bit <<= 1, swap(bz, bz1)) {
            memset(f[bz1], 0, sizeof(f[bz1]));
            for (int sig = 0; sig < 2; sig ++) {
                for (int n_bit = 0; n_bit < 2; n_bit ++) {
                    bool sig1 = max(sig + n_bit - ((n & bit) > 0), 0);
                    int v = n_bit + 1;
                    work(f[bz][sig], f[bz1][sig1], n_bit, bit, d, 0, 0, 0, 1);

                }
            }
        }
        return f[bz][0][ind(v)];
    }
    ll _two_cell_hit_after_0_n_step(int x1, int y1, int x2, int y2, int n) {//两个细胞0~n秒撞在一起的部分
        x2 = abs(x2 - x1), y2 = abs(y2 - y1);
        vector<int>d;
        d.push_back(x2 + y2), d.push_back(abs(x2 - y2));
        return  _mD_hit_after_0_n_step(d, n);
    }
    ll _two_cell_after_0_n_step(int x1, int y1, int x2, int y2, int n) {//两个细胞相互作用后的结果
        return (_one_cell_after_0_n_step(n) - _two_cell_hit_after_0_n_step(x1, y1, x2, y2, n)) * 2;
    }
}
using  namespace cell_xor_split;
void output(ll x){
    vector<int> d;
    while (x) d.push_back(x % 10), x /= 10;
    reverse(d.begin(), d.end());
    for (auto u:d)
        printf("%d",u);
}
int main() {
    int n, x1, y1, x2, y2;
    cin>>n>>x1>>y1>>x2>>y2;
    output(cell_xor_split::_two_cell_after_0_n_step(x1, y1, x2, y2, n - 1));
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 5ms, 内存消耗: 484K, 提交时间: 2018-10-05 21:22:32

#include<bits/stdc++.h>

#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define Id(a,b) ((a)*2+(b))

using namespace std;

typedef __int128 LL;
typedef double db;

LL solve1(LL n){
	LL ret=0;
	LL pre=1;
	fd(i,30,0){
		ret=ret*5;
		if ((n&(1<<i))>0){
			ret=ret+pre;
			pre=pre*4;
		}
	}
	return ret;
}

LL f[40][7][7];//-3..3

LL solve2(LL n,LL x,LL y){
	fd(i,30,0){
		fo(vx,0,6){
			fo(vy,0,6){
				fo(ax,-2,2)
					fo(ay,-2,2)
					if ((ax+ay)%2==0&&abs(ax)+abs(ay)<=2){
						LL v=max(abs(ax),abs(ay));
						v=1<<(2-v);
						if (ax==0&&ay==0)v=v+1;
						int vx_=(vx-3)*2+ax+3-((x&(1<<i))>0),vy_=(vy-3)*2+ay+3-((y&(1<<i))>0);
						if (vx_>=0&&vx_<7&&vy_>=0&&vy_<7){
							f[i][vx_][vy_]+=f[i+1][vx][vy]*v;
						}
					}
			}
		}
		if ((n&(1<<i))>0){
			LL val[7][7];
			fo(vx,0,6)fo(vy,0,6)val[vx][vy]=0;
			val[3][3]=1;
			fd(w,30,i){
				LL tmp[7][7];
				fo(vx,0,6)fo(vy,0,6){tmp[vx][vy]=val[vx][vy];val[vx][vy]=0;}
				if (w==i||((n&(1<<w))==0)){
					fo(vx,0,6)
						fo(vy,0,6){
							int vx_=(vx-3)*2+3-((x&(1<<w))>0),vy_=(vy-3)*2+3-((y&(1<<w))>0);
							if (vx_>=0&&vx_<7&&vy_>=0&&vy_<7)val[vx_][vy_]+=tmp[vx][vy];
						}
				}
				else
					fo(vx,0,6){
						fo(vy,0,6){
							fo(ax,-2,2)
								fo(ay,-2,2)
								if ((ax+ay)%2==0&&abs(ax)+abs(ay)<=2){
									int v=max(abs(ax),abs(ay));
									v=1<<(2-v);
									int vx_=(vx-3)*2+ax+3-((x&(1<<w))>0),vy_=(vy-3)*2+ay+3-((y&(1<<w))>0);
									if (vx_>=0&&vx_<7&&vy_>=0&&vy_<7){
										val[vx_][vy_]+=tmp[vx][vy]*v;
									}
								}
						}
					}
			}
			fo(a,0,6)fo(b,0,6)f[i][a][b]+=val[a][b];
		}
	}
	LL ret=f[0][3][3];
	return ret;
}

int digiw,digi[1000];

void putans(LL v){
	if (v==0){putchar('0');putchar('\n');return;}
	for(;v;v=v/10)digi[++digiw]=v%10;
	for(;digiw;digiw--)putchar('0'+digi[digiw]);
	putchar('\n');
}

int main(){
	int n,x1,y1,x2,y2;
	cin>>n>>x1>>y1>>x2>>y2;
	LL x=abs(x1-x2),y=abs(y1-y2);
	LL ans=solve1(n)-solve2(n,x,y);
	ans=ans*2;
	putans(ans);
	return 0;
}

上一题