OJ 1177 1178 1179
一.电路图A
第一问,容易看出$右拐次数=左拐次数+4$,$左拐+右拐=n$,所以$右拐=n/2-2$,相当于$C_{n}^{n/2-2}$
第二问,总个数除去最左端,最右端,最上方,最下方的电阻,整个电路被分成$4$段,每一段都有偶数个电阻,答案就是将$n$分成$4$个偶数的情况,相当于将$n/2$分成任意数的情况,用隔板法,答案就是$C_{n/2-1}^{3}$,排除旋转的影响,答案还要除以$4$。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <deque>
#include <string>
using namespace std;
inline long long read(){
long long ans = 0, f = 1;
char ch = getchar();
while(!isdigit(ch))
f *= (ch == '-') ? -1 : 1, ch = getchar();
do ans = (ans << 1) + (ans << 3) + (ch ^ 48), ch = getchar();
while(isdigit(ch));
return ans * f;
}
const int MOD = 1e9+7, MAXN = 1e7 + 1;
int fac[MAXN], inv[MAXN];
int pow(int a,int p){
int ans = 1;
while(p){
if(p & 1) ans = (long long)ans * a % MOD;
a = (long long)a * a % MOD, p >>= 1;
}
return ans;
}
inline int C(int n,int m){
return (long long)fac[n] * inv[m] % MOD * inv[n-m] % MOD;
}
int main(){
int n = read(), ans1, ans2;
fac[0] = 1;
for(int i=1; i<=n; i++)
fac[i] = (long long)fac[i-1] * i % MOD;
inv[n] = pow(fac[n], MOD-2);
for(int i=n-1; i>=0; i--)
inv[i] = (long long)inv[i+1] * (i+1) % MOD;
ans1 = C(n, n/2-2);
ans2 = (long long)C(n/2+1, 3) * n % MOD * pow(4, MOD-2) % MOD;
printf("%d\n%d", ans1, ans2);
return 0;
}
二.电路图B
区间修改,区间查询,一看就是线段树,关键在于合并标记如何合并。
可将一个标记记为$\frac{ax+b}{cx+d}$,用四个数表示为$\{a,b,c,d\}$,串联一个电阻就是$\{0,R,0,1\}$,并联一个电阻就是$\{R,0,1,R\}$
最关键是mix操作,将$\{a,b,c,d\}$和$\{i,j,k,p\}$合成为$\{ai+cj,bi+dj,ak+cp,bk+dp\}$,最终就转化为线段树加标记的问题了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
long long read(){
long long ans = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
f *= (ch == '-') ? -1 : 1, ch = getchar();
do ans = ((ans << 1) + (ans << 3) + (ch ^ 48)), ch = getchar();
while(ch >= '0' && ch <= '9');
return ans * f;
}
const int MAXN = 250001, MAXM = 250001;
struct sign{double a, b, c, d;};
struct Segment{
int l, r;
double maxNum, minNum;
sign add;
bool isSigned;
}seg[MAXN*4];
int a[MAXN];
void change(int x,sign fa){
sign t = seg[x].add;
seg[x].isSigned = true;
double a, b, c, d;
a = t.a * fa.a + t.c * fa.b;
b = t.b * fa.a + t.d * fa.b;
c = t.a * fa.c + t.c * fa.d;
d = t.b * fa.c + t.d * fa.d;
seg[x].add = (sign){1, b/a, c/a, d/a};
seg[x].maxNum = (seg[x].maxNum * fa.a + fa.b) / (seg[x].maxNum * fa.c + fa.d);
seg[x].minNum = (seg[x].minNum * fa.a + fa.b) / (seg[x].minNum * fa.c + fa.d);
}
void spread(int x){
if(seg[x].isSigned){
change(x*2, seg[x].add);
change(x*2+1, seg[x].add);
seg[x].isSigned = false;
seg[x].add = (sign){1, 0, 0, 1};
}
}
void build(int l,int r,int x=1){
seg[x].l = l, seg[x].r = r;
seg[x].add = (sign){1, 0, 0, 1};
if(l == r){
seg[x].maxNum = seg[x].minNum = a[l];
return;
}
int mid = (l + r) >> 1;
build(l, mid, x*2);
build(mid+1, r, x*2+1);
seg[x].maxNum = max(seg[x*2].maxNum, seg[x*2+1].maxNum);
seg[x].minNum = min(seg[x*2].minNum, seg[x*2+1].minNum);
}
void point(int l,int r,sign vis,int x=1){
if(l <= seg[x].l && seg[x].r <= r){
change(x, vis);
return;
}
spread(x);
if(seg[x*2].r >= l) point(l, r, vis, x*2);
if(seg[x*2+1].l <= r) point(l, r, vis, x*2+1);
seg[x].maxNum = max(seg[x*2].maxNum, seg[x*2+1].maxNum);
seg[x].minNum = min(seg[x*2].minNum, seg[x*2+1].minNum);
}
double ask(int l,int r,int type,int x=1){
if(l <= seg[x].l && seg[x].r <= r)
return (type == 1) ? seg[x].maxNum : seg[x].minNum;
spread(x);
double ans = (type == 1) ? 0 : 1e9;
if(seg[x*2].r >= l) (type == 1) ? ans = max(ans, ask(l, r, type, x*2)) : ans = min(ans, ask(l, r, type, x*2));
if(seg[x*2+1].l <= r) (type == 1) ? ans = max(ans, ask(l, r, type, x*2+1)) : ans = min(ans, ask(l, r, type, x*2+1));
return ans;
}
int main(){
int n = read();
for(int i=1; i<=n; i++)
a[i] = read();
build(1, n);
int m = read();
for(int i=1; i<=m; i++){
int op = read(), l = read(), r = read();
if(op == 1) printf("%.10lf\n", ask(l, r, 1));
else if(op == 2) printf("%.10lf\n", ask(l, r, 2));
else{
int R = read();
if(op == 3) point(l, r, (sign){1, R, 0, 1});
else point(l, r, (sign){R, 0, 1, R});
}
}
return 0;
}
三.电路图C(待填坑)
来源:https://www.cnblogs.com/PHDHD/p/12276110.html
