2019-12-5 CSP认证-魔数AC代码

2019-12-5 CSP认证-魔数AC代码


考点:思维+BFS+线段树
在这里插入图片描述
C++代码如下:

// An highlighted block
// Powered by Qiping Yan
#include<cstdio>
#include<unordered_map>
#include<queue>
using namespace std;
typedef unsigned long long uLL;
const int N = 1000000 + 10;
const uLL MOD = 2009731336725594113;

unordered_map<uLL,int> mp;
uLL U[5] = {314882150829468584,427197303358170108,1022292690726729920,1698479428772363217,2006101093849356424};
uLL f[40],arr[N][40];
int g[40][40];
int n,q;

struct segtree{
	int L,R;
	int s[40];
	int res;
	int tag;

	void convert(int target){
		int tmp[40];
		for(int i = 1 ; i <= 32 ; i++ )
			tmp[i] = s[g[i][target]];
		for(int i = 1 ; i <= 32 ; i++ )
			s[i] = tmp[i];
		res = s[28];
		if(tag == 0) tag = target;
		else tag = g[tag][target];
	}
};

segtree tree[N << 2];

uLL mul(uLL a,uLL b);
void get_convert();
void build(int p,int L,int R);
void pushdown(int p);
int ask(int p,int L,int R);
void change(int p,int L,int R,int k);
int main(){
	get_convert();
	scanf("%d%d",&n,&q);
	for(int i = 1 ; i <= n ; i++ )
		for(int j = 1 ; j <= 32 ; j++ ){
			if(i == 1) arr[i][j] = f[j] % MOD;
			else arr[i][j] = (f[j] + arr[i - 1][j]) % MOD;
		}
	build(1,1,n);
	while(q--){
		int L,R;
		scanf("%d%d",&L,&R);

		int ans = ask(1,L,R);
		printf("%d\n", ans);
		change(1,L,R,ans % 5);
	}
	return 0;
}

uLL mul(uLL a,uLL b){
	uLL ret = 0;
	while(b){
		if(b & 1) ret = (ret + a) % MOD;
		a = (a + a) % MOD;
		b >>= 1;
	}
	return ret;
}
void get_convert(){
	queue<uLL> que;
	int cnt = 1;
	for(int i = 0 ; i < 5 ; i++ ){
		que.push(U[i]);
		mp[U[i]] = cnt++;
	}
	while(!que.empty()){
		uLL val = que.front(); que.pop();
		f[mp[val]] = val;
		for(int i = 0 ; i < 5 ; i++ ){
			uLL tmp = mul(val,U[i]);
			if(mp[tmp]) continue;
			mp[tmp] = cnt++;
			que.push(tmp);
		}
	}
	for(int i = 1 ; i <= 32 ; i++ )
		for(int j = i ; j <= 32 ; j++ )
			g[i][j] = g[j][i] = mp[mul(f[i],f[j])];
	return ;
}

void build(int p,int L,int R){
	tree[p].L = L; tree[p].R = R;
	if(L == R){
		for(int i = 1 ; i <= 32 ; i++ )
			tree[p].s[i] = arr[L][i] % 2019;
		tree[p].res = tree[p].s[28];
		tree[p].tag = 0;
		return ;
	}
	int mid = (L + R) >> 1;
	build(p * 2,L,mid);
	build(p * 2 + 1,mid + 1,R);
	for(int i = 1 ; i <= 32 ; i++ )
		tree[p].s[i] = tree[p * 2].s[i] + tree[p * 2 + 1].s[i];
	tree[p].res = tree[p].s[28];
	tree[p].tag = 0;
	return ;
}

void pushdown(int p){
	if(!tree[p].tag) return ;
	tree[2 * p].convert(tree[p].tag);
	tree[2 * p + 1].convert(tree[p].tag);
	tree[p].tag = 0;
	return ;
}

int ask(int p,int L,int R){
	if(tree[p].L >= L && tree[p].R <= R){
		return tree[p].res;
	}
	pushdown(p);
	int mid = (tree[p].L + tree[p].R) >> 1;
	int res = 0;
	if(mid >= L) res = ask(p * 2,L,R);
	if(mid < R) res += ask(p * 2 + 1,L,R);
	return res;
}

void change(int p,int L,int R,int k){
	if(tree[p].L >= L && tree[p].R <= R){
		tree[p].convert(k + 1);
		return ;
	}
	pushdown(p);
	int mid = (tree[p].L + tree[p].R) >> 1;
	if(mid >= L) change(p * 2,L,R,k);
	if(mid < R) change(p * 2 + 1,L,R,k);
	for(int i = 1 ; i <= 32 ; i++ )
		tree[p].s[i] = tree[p * 2].s[i] + tree[p * 2 + 1].s[i];
	tree[p].res = tree[p].s[28];
	return ;
}

参考博客
https://www.cnblogs.com/1625–H/p/12745977.html

你可能感兴趣的:(ACM,C++)