• 2021-07-12 部分集训题目题解


    一时暴力一时爽,一直暴力一直爽(两个亿

    染色

    题目传送门

    Description

    Solution

    我们考虑先染斜对角线再染行,那么可以发现的是,如果一个斜对角线经过的行都染了色,那选不选这条线都不会有影响。

    所以,我们假设一个斜对角线经过行的区间是 ([l_i,r_i]),那么问题就是选出一些区间,并在这些区间的并中选出一些元素,使得没有一个被选中的区间中每个位置的元素都被选中。可以看出,选元素就是选哪些行被染色。

    这个分类讨论然后做个前缀和,复杂度 (Theta(n^3))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define MAXN 2005
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c != ' ' && c != '
    ') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    template <typename T> void chkmax (T &a,T b){a = max (a,b);}
    template <typename T> void chkmin (T &a,T b){a = min (a,b);}
    
    #define pii pair<int,int>
    #define se second
    #define fi first
    vector <pii> S;
    
    int n,m,mod,pw[MAXN],f[MAXN][MAXN],pre[MAXN][MAXN];
    
    int mul (int a,int b){return 1ll * a * b % mod;}
    int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
    int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
    void Add (int &a,int b){a = add (a,b);}
    
    signed main(){
    	freopen ("coloring.in","r",stdin);
    	freopen ("coloring.out","w",stdout);
    	read (n,m,mod),S.resize (n + m + 1);int tot = 0;
    	for (Int i = 1;i <= n + m - 1;++ i) ++ tot,S[i] = {max (1,i - m + 1),min (n,i)};
    	pw[0] = 1;for (Int i = 1;i <= max (n,m);++ i) pw[i] = add (pw[i - 1],pw[i - 1]);
    	for (Int i = 0;i <= n;++ i) pre[0][i] = 1;
    	for (Int i = 1;i <= tot;++ i){
    		for (Int j = 0;j <= S[i].se - S[i].fi;++ j){
    			for (Int k = 0;k < i;++ k){
    				if (S[i].se - j > S[k].se){
    					if (S[k].se < S[i].fi) Add (f[i][j],mul (pre[k][n],pw[S[i].se - S[i].fi - j]));
    					else Add (f[i][j],mul (pre[k][n],pw[S[i].se - S[k].se - j - 1]));
    				}
    				else Add (f[i][j],f[k][j + S[k].se - S[i].se]);
    			}
    		}
    		for (Int j = 0;j <= n;++ j) pre[i][j] = add (j ? pre[i][j - 1] : 0,f[i][j]);
    	}
    	int ans = 0;
    	for (Int i = 0;i <= tot;++ i) Add (ans,pre[i][n]);
    	write (ans),putchar ('
    ');
    	return 0;
    }
    

    生命游戏

    题目传送门

    Description

    Solution

    对于 (n=1) 的情况可以想到的是,每时每刻它存活格子都是斜 (45^circ)

    对于 (n=2) 的情况,可以想到如果两个横纵坐标和的奇偶性相同,那么两者才会产生影响,影响如下:

    可以看出,对于时刻 (t) ,贡献就是 ((a+t) imes (b+t)) 的形式。

    考虑对此进行拓展,可以想到,从两个点相交到另两个点相交这一段时间的贡献显然就是关于 (t) 的三次函数形式。那么我们就可以用扫描线求出一个时刻的贡献,然后暴力插值。

    复杂度 (Theta(n^4+qlog n))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define inv2 499122177
    #define inv6 166374059
    #define mxv 1000000000
    #define mod 998244353
    #define int long long
    #define MAXN 205
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c != ' ' && c != '
    ') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    template <typename T> void chkmax (T &a,T b){a = max (a,b);}
    template <typename T> void chkmin (T &a,T b){a = min (a,b);}
    
    #define fi first
    #define se second
    #define pii pair<int,int>
    
    int n,q;
    int mul (int a,int b){return 1ll * a * b % mod;}
    int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
    int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
    void Add (int &a,int b){a = add (a,b);}
    void Sub (int &a,int b){a = dec (a,b);}
    
    vector <pii> vp[2];
    
    struct node{
    	int x,l,r;
    	bool t;
    };
    
    int a[MAXN],y[MAXN];
    int calc (int o,int d){//计算奇偶性为t的点在d时刻的贡献
    	vector <node> v;
    	memset (a,0,sizeof (a));
    	int uni = 0,res = 0,tmp = 0;
    	for (pii it : vp[o]){
    		int yl = it.se - (d + 1 >> 1),yr = it.se + (d >> 1) + 1;
    		y[++ uni] = yl,y[++ uni] = yr,
    		v.push_back (node{it.fi - (d + 1 >> 1),yl,yr,1}),
    		v.push_back (node{it.fi + (d >> 1) + 1,yl,yr,0});
    	}
    	sort (y + 1,y + uni + 1),uni = unique (y + 1,y + uni + 1) - y - 1,sort (v.begin(),v.end(),[](node s1,node s2){return s1.x < s2.x;});
    	for (Int i = 0;i < v.size();++ i){
    		v[i].l = lower_bound (y + 1,y + uni + 1,v[i].l) - y,v[i].r = lower_bound (y + 1,y + uni + 1,v[i].r) - y;
    		for (Int j = v[i].l;j < v[i].r;++ j) 
    			if (v[i].t){
    				if (!a[j]) tmp += (y[j + 1] - y[j]);
    				a[j] ++;
    			}
    			else{
    				a[j] --;
    				if (!a[j]) tmp -= (y[j + 1] - y[j]);
    			}
    		if (i != v.size()) Add (res,mul (tmp,v[i + 1].x - v[i].x));
    	}
    	return res;
    }
    
    struct fuc{
    	int y[4];
    	fuc(){for (Int i = 0;i < 3;++ i) y[i] = 0;}
    	void makeit (){y[0] = mul (mod - inv6,y[0]),y[1] = mul (inv2,y[1]),y[2] = mul (mod - inv2,y[2]),y[3] = mul (inv6,y[3]);}
    	int getit (int d){
    		int pl[4] = {},pr[4] = {},res = 0;
    		pl[0] = 1;for (Int i = 0;i < 3;++ i) pl[i + 1] = mul (pl[i],dec (d,i));
    		pr[3] = 1;for (Int i = 3;i > 0;-- i) pr[i - 1] = mul (pr[i],dec (d,i));
    		for (Int i = 0;i <= 3;++ i) Add (res,mul (mul (pl[i],pr[i]),y[i]));
    		return res;
    	}
    };
    
    fuc getit (int o,int s,int l,int r){
    	fuc t;
    	for (Int i = l;i <= r && i <= l + 3;++ i) Add (s,calc (o,i)),t.y[i - l] = s;
    	t.makeit();return t;
    }
    
    vector <int> tim[2];
    vector <fuc> sht[2];
    
    void buildit (int o){
    	tim[o].push_back (0),tim[o].push_back (mxv + 1);
    	for (pii it1 : vp[o]) for (pii it2 : vp[o]) tim[o].push_back (max (abs (it1.fi - it2.fi),abs (it1.se - it2.se)));
    	sort (tim[o].begin(),tim[o].end()),tim[o].erase (unique (tim[o].begin(),tim[o].end()),tim[o].end());
    	fuc t;for (Int i = 0,lst = 0;i < tim[o].size() - 1;++ i) t = getit (o,lst,tim[o][i],tim[o][i + 1] - 1),sht[o].push_back (t),lst = t.getit (tim[o][i + 1] - 1 - tim[o][i]);
    }
     
    int fuckit (int o,int T){
    	int pos = upper_bound (tim[o].begin(),tim[o].end(),T) - tim[o].begin() - 1;
    	return sht[o][pos].getit (T - tim[o][pos]);
    }
     
    signed main(){
    	freopen ("lifegame.in","r",stdin);
    	freopen ("lifegame.out","w",stdout);
    	read (n,q);
    	for (Int i = 1;i <= n;++ i){
    		int x,y;read (x,y);
    		vp[x + y & 1].push_back ({x + y >> 1,x + mxv - y >> 1});
    	}
    	buildit (0),buildit (1);
    	while (q --> 0){
    		int T;read (T);
    		write (add (fuckit (0,T),fuckit (1,T))),putchar ('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    Oracle 启动关闭
    GridView 自动序号
    提高数据库处理查询速度
    Linux目录结构
    GridView 全选
    Linux 窗口启动和命令行启动设置
    Oracle 备份
    二进制部署K8S集群(三)前置准备工作之准备签发证书环境
    nginx的location详解
    二进制部署K8S集群(七)Master节点之kubeapiserver集群部署
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/15003793.html
Copyright © 2020-2023  润新知