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

考虑两种操作的实际意义:

  1. a->a+1
  2. 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 ;
}

posted @ 2019-08-17 10:02  tyqtyq~!  阅读(92)  评论(0编辑  收藏  举报