JZOJ-PJ817-SOL
题面见JZOJ
T1
考虑设输入数组为\(p\), 答案数组为\(a\)(\(a_i表示是否是男\))
那么有:
\[\left\{
\begin{aligned}
p_1 &= a_1+a_2 \\
p_2 &= a_1+a_2+a_3 \\
p_3 &= a_2+a_3+a_4 \\
p_i &= a_{i-1}+a_{i}+a_{i+1} \\
p_{n-1} &= a_{n-2}+a_{n-1}+a_{n} \\
p_{n} &= a_{n-1}+a_{n} \\
\end{aligned}
\right.
\]
要求的,就是该方程解的个数,n个未知数n个方程,出现多解只有可能是两个方程等价,发现只有开头有可能有两种情况,暴力即可
T2
考虑两种操作的实际意义:
- a->a+1
- a->(a/a+1)
一个x电容并联后变成x+1会变大,串联后变成x/(x + 1)会变小,我们最终要把需要的电容变成1,那么我们就反着推,如果当前电容大于1,最后一次操作就是并联,并联前是x-1(即(a-b)/b),如果当前电容小于1,最后一次操作就是串联,串联前就是x/(1 - x)(即a/(b-a)),不难发现两者就是a和b的辗转相减,那么我们只要辗转相除加速即可,商的和即为答案。
T3
线段树+扫描线直接上
T4
发现最终答案之和有几个度数为1的点、有几个度数为2的点有关。所以可以设f[i][j]表示当前已经加入了i个度数为1的点,j个度数为2的点的总方案数。转移的时候考虑下一个点的连边方式。但是直接这样做相当于把连边又加了一个顺序,会有重复。可以强制规定在度数为1的点加完之后才可以加度数为2的点。
那么如何转移?我们考虑如何加入度数为2的点,明显需要插入在一个环/链中间
f[i+1][j]<-f[i-1][j]i; (j=0)
f[i][j+1]<-f[i-2][j]i(i-1)/2;
f[i][j+1]<-f[i][j+1]+f[i+2][j-2]j(j-1)/2;
f[i][j+1]<-f[i][j-1]i*j;
DP即可
Code:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int _ = 300005 ;
int t,n; int a[_], p[_];
int main(){
//freopen("cti.in", "r", stdin) ;
freopen("cti.out", "w", stdout) ;
scanf("%d",&t) ;
while(t-->0){
memset(p,0,sizeof(p)); memset(a,0,sizeof(a));
scanf("%d",&n) ;
for(int i=1;i<=n;++i) scanf("%d",&p[i]) ;
a[1]=0 ;
int gans=1, ans=0;
for(int i=2;i<=n;++i){
a[i] = p[i-1]-a[i-1]-a[i-2] ; if(a[i]>1||a[i]<0) gans=0 ;
}
if(p[n]!=a[n]+a[n-1]) gans = 0 ;
ans+=gans; gans=0;
if(p[1]!=0){
a[1]=1 ;
gans=1;
for(int i=2;i<=n;++i){
a[i] = p[i-1]-a[i-1]-a[i-2] ; if(a[i]>1||a[i]<0) gans=0 ;
}
if(p[n]!=a[n]+a[n-1]) gans = 0 ;
}
cout<<ans+gans<<endl;
}
}
#include<iostream>
#include<cstdio>
using namespace std;
#define int long long
int gcd(int a, int b){return b?gcd(b,a%b):a;}
int slove(int a, int b){
if(b == 0) return 0 ;
return a/b+slove(b,a%b) ;
}
int t,a,b ;
signed main(){
scanf("%lld",&t) ;
while(t-->0){
scanf("%lld%lld",&a,&b) ;
printf("%lld\n",slove(a, b)) ;
}
}
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<deque>
#define int long long
using namespace std;
#define lson i<<1,l,m
#define rson i<<1|1,m+1,r
const int maxn=100005;
int x[maxn];
struct node{
int l,r,h;
int d;
node() {}
node(int l,int r,int h,int d):l(l),r(r),h(h),d(d) {}
bool operator < (const node &a)const{
return h<a.h;
}
} line[maxn];
int cnt[maxn<<2];
int sum[maxn<<2];
void pushup(int i,int l,int r){
if(cnt[i]) sum[i]=x[r+1]-x[l];
else sum[i]=sum[i<<1]+sum[i<<1|1];
}
void update(int ql,int qr,int v,int i,int l,int r){
if(ql<=l && qr>=r){
cnt[i]+=v;
pushup(i,l,r);
return ;
}
int m=(l+r)>>1;
if(ql<=m)update(ql,qr,v,lson);
if(qr>m)update(ql,qr,v,rson);
pushup(i,l,r);
}
signed main(){
freopen("degenerate.in", "r", stdin) ;
freopen("degenerate.out", "w", stdout) ;
int q ; scanf("%d",&q) ;
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
int n=0,m=0;
for(int i=1; i<=q; i++){
int x1,y1,x2,y2;
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
x[++n]=x1;
x[++n]=x2;
line[++m]=node(x1,x2,y1,1);
line[++m]=node(x1,x2,y2,-1);
}
sort(x+1,x+1+n);
sort(line+1,line+1+m);
int k=1;
k=unique(x+1,x+n+1)-x-1;
int ans=0;
for(int i=1; i<m; i++){
int l=lower_bound(x+1,x+k+1,line[i].l)-x;
int r=lower_bound(x+1,x+k+1,line[i].r)-x;
r--;
if(l<=r)update(l,r,line[i].d,1,1,k-1);
ans+=sum[1]*(line[i+1].h-line[i].h);
}
printf("%lld\n",ans);
}
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std ;
#define int unsigned long long
#define Mod 998244353
int n, cnt1, cnt2, ans;
int f[2005][2005];
const int C=499122177 ;
int power(int a,int b){
int res=1, car=a;
while(b){
if(b&1) (res*=car)%=Mod ;
(car*=car)%=Mod ;
b>>=1 ;
}
return res ;
}
signed main(){
freopen("map.in", "r", stdin) ;
freopen("map.out", "w", stdout) ;
scanf("%lld",&n) ;
for(int i=1,p=0;i<=n;++i) { scanf("%lld", &p); p==1?++cnt1:++cnt2; }
f[0][0] = 1 ;
for(int i=0;i<=n;++i){
for(int j=0;j<=n;++j){
if(i>=1 && j==0)(f[i+1][j]+=f[i-1][j]*i)%=Mod;
if(i>=2)(f[i][j+1]+=f[i-2][j]*i*(i-1)*C)%=Mod;
if(j>=2)(f[i][j+1]+=f[i][j+1]+f[i+2][j-2]*j*(j-1)*C)%=Mod;
if(j>=1)(f[i][j+1]+=f[i][j-1]*i*j)%=Mod;
}
}
for(int i=0;i<=n;++i)
for(int j=0;j<=n;++j)
printf("f[%lld][%lld]=%lld\n", i, j, f[i][j]) ;
cout<<f[cnt1][cnt2]<<endl ;
}