zoukankan      html  css  js  c++  java
  • 联赛模拟测试 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)

  • 相关阅读:
    Mysql系列【解决mysql连接数太多】
    并发编程系列【线程池七大核心参数】
    C信号处理的基础
    设计模式之Command
    Ext文件系统
    内存管理
    设计模式之Decorator Pattern
    设计模式之singleton
    Quicklz压缩算法
    设计模式之Factory
  • 原文地址:https://www.cnblogs.com/Vocanda/p/13832228.html
Copyright © 2011-2022 走看看