联赛模拟测试 17

A. 简单的区间

CDQ裸题,每次考虑跨过区间中点的区间的贡献。分最大值在左和在右的两种情况。
(suml) 为左边端点到中点的和,(sumr) 同理,那么要求的就是如下柿子:

[suml+sumr-maxequiv 0(mod k) ]

然后移项得到

[sumlequiv -sumr+max(mod k) ]

根据这个柿子求和即可。

代码



#include<bits/stdc++.h>
using namespace std;
const int L = 1 << 20;
char buffer[L],*S,*T;
#define gc (S == T && (T = (S = buffer) + fread(buffer,1,L,stdin),S == T) ? EOF : *S++)
#define read() ({int s = 0,f = 1;char ch = gc;for(;!isdigit(ch);ch = gc)if(ch == '-')f = -1;for(;isdigit(ch);ch = gc)s = s * 10 + ch - '0';s * f;})
#define ll long long
const int maxn = 1e6+10;
ll sum[maxn];
ll a[maxn];
int n,k;
int ans;
int cnt[maxn];
inline void CDQ(int l,int r){
	if(l == r)return;
	int mid = (l + r) >> 1;
	CDQ(l,mid);
	CDQ(mid+1,r);
	ll i = mid,j = mid + 1,mxl = a[i],mxr = a[j],suml = 0,sumr = a[j] % k;
	cnt[sumr]++;
	while(i >= l){
		suml = (suml + a[i]) % k;
		mxl = max(mxl,a[i]);
		while(j + 1 <= r && mxl >= max(mxr,a[j + 1])){
			j++;
			mxr = max(mxr,a[j]);
			sumr = (sumr + a[j]) % k;
			cnt[sumr]++;
		}
		if(mxl >= mxr){
			ll jl = (-suml + mxl) % k;
			jl = (jl + k) % k;
			ans += cnt[jl % k];
		}
		--i;
	}
	i = mid,j = mid + 1,mxl = a[i],mxr = a[j],suml = a[i] % k,sumr = 0;
	ll sum = 0;
	for(int p = mid + 1;p <= r;++p)cnt[sum=(sum+a[p]) % k] = 0;
	cnt[suml]++;
	while(j <= r){
		sumr = (sumr + a[j]) % k;
		mxr = max(mxr,a[j]);
		while(i - 1 >= l && mxr > max(mxl,a[i - 1])){
			i--;
			mxl = max(mxl,a[i]);
			suml = (suml + a[i]) % k;
			cnt[suml]++;
		}
		if(mxr > mxl){
			ll jl = (-sumr + mxr) % k;
			jl = (jl + k) % k;
			ans += cnt[jl % k];
		}
		++j;
	}
	sum = 0;
	for(int p = mid;p >= l;--p){
		cnt[sum=(sum + a[p]) % k] = 0;
	}
}
int main(){
	n = read(),k = read();
	for(int i = 1;i <= n;++i)a[i] = read();
	CDQ(1,n);
	printf("%d
",ans);
	return 0;
}

B. 简单的玄学

根据容斥,得到不满足条件的方案为 (frac{A_{2^n}^m}{2^{nm}})
然后减一下即可,下边我们需要约分,容易发现只有因子 (2) 会被约分,分子上的 (2) 的次方可以转化为 ((m-1)!)(2) 的个数。
然后我们就可以以 (O(logm)) 的复杂度求出,然后算一下就行了。

代码



#include<bits/stdc++.h>
using namespace std;
const int L = 1 << 20;
const int mod = 1e6 + 3;
const int ny = 500002;
char buffer[L],*S,*T;
#define ll long long
#define gc (S == T && (T = (S = buffer) + fread(buffer,1,L,stdin),S == T) ? EOF : *S++)
#define read() ({ll s = 0,f = 1;char ch = gc;for(;!isdigit(ch);ch = gc)if(ch == '-')f = -1;for(;isdigit(ch);ch = gc)s = s * 10 + ch - '0';s * f;})
inline ll qpow(ll x,ll y){
	ll ans = 1;
	while(y){
		if(y & 1)ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans % mod;
}
int main(){
	freopen("random.in","r",stdin);
	freopen("random.out","w",stdout);
	ll n = read(),m = read();
	if(log2(m) > n)return puts("1 1"),0;
	ll tmp = qpow(2,n);
	ll mu = qpow(tmp,m);
	ll zi = 1;
	ll cnt = n;
	for(ll i = 0;i < m && zi;i++){
		zi = zi % mod * (tmp - i) % mod; 
	}
	for(ll i = 2;i < m;i <<= 1)cnt += (m - 1) / i; 
	mu = mu * qpow(ny,cnt) % mod;
	zi = zi * qpow(ny,cnt) % mod;
	printf("%lld %lld
",(mu-zi+mod) % mod,mu % mod);
	return 0;
}

C. 简单的填数

模拟,咕咕咕。

D. 聪聪和可可

预处理猫和鼠在什么位置时,猫的下一步是啥。
设猫在 (i) ,鼠在 (k) ,如果 (j)(k) 的距离为 (i)(k) 的距离减一,那么下一步就是 (j)
每次取 (min) ,因为走编号最小的点,然后记忆化搜索就行了。

代码



#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3+10;
#define db double
int nxt[maxn][maxn],dis[maxn][maxn];
struct Node{
	int v,next;
}e[maxn<<1];
int head[maxn],tot;
int deg[maxn];
db f[maxn][maxn];
int vis[maxn];
inline void Add(int x,int y){
	e[++tot].v = y;
	e[tot].next = head[x];
	head[x] = tot;
}
queue<int>q;
inline void spfa(int s){
	dis[s][s] = 0;
	q.push(s);vis[s] = 1;
	while(!q.empty()){
		int x = q.front();q.pop();
		vis[x] = 0;
		for(int i = head[x];i;i = e[i].next){
			int v = e[i].v;
			if(dis[s][v] > dis[s][x] + 1){
				dis[s][v] = dis[s][x] + 1;
				if(!vis[v]){
					q.push(v);
					vis[v] = 1;
				}
			}
		}
	}
}
inline db dfs(int cat,int mouse){
	if(f[cat][mouse])return f[cat][mouse];
	if(cat == mouse)return 0;
	int to1 = nxt[cat][mouse];
	int to2 = nxt[to1][mouse];
	if(to1 == mouse || to2 == mouse)return 1;
	f[cat][mouse] += 1.0;
	for(int i = head[mouse];i;i = e[i].next){
		int v = e[i].v;
		f[cat][mouse] += dfs(to2,v)/(double)(deg[mouse]+1);
	}
	f[cat][mouse] += dfs(to2,mouse)/(double)(deg[mouse]+1);
	return f[cat][mouse];
}
int main(){
	freopen("cchkk.in","r",stdin);
	freopen("cchkk.out","w",stdout);
	memset(dis,0x3f,sizeof(dis));
	memset(nxt,0x3f,sizeof(nxt));
	int n,m;scanf("%d%d",&n,&m);
	int s,t;scanf("%d%d",&s,&t);
	for(int i = 1;i <= m;++i){
		int x,y;scanf("%d%d",&x,&y);
		Add(x,y);
		Add(y,x);
		deg[x]++;deg[y]++;
	}
	for(int i = 1;i <= n;++i)spfa(i);
	for(int x = 1;x <= n;++x){
		for(int i = head[x];i;i = e[i].next){
			int v = e[i].v;
			for(int j = 1;j <= n;++j){
				if(dis[x][j] - 1 == dis[v][j]){
					nxt[x][j] = min(nxt[x][j],v);
				}
			}
		}
	}
	printf("%.3lf
",dfs(s,t));
	return 0;
}

(Never Give Up)

原文地址:https://www.cnblogs.com/Vocanda/p/13832228.html