8 Zhengrui takes notes

T1

I think it's still a water problem. We can just do it hard with bitset.

code:

#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N 20100
#define M number
using namespace std;

const int INF=0x3f3f3f3f;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

bitset<20100> bit[N],b0,b1,b2,b3;
char s[N];
int n,m;

int main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=m;i++){
        b0.reset();b1.reset();b2.reset();b3.reset();
        scanf("%s",s+1);
        for(int j=1;j<=n;j++){
            if(s[j]=='0') b0[j]=1;
            else if(s[j]=='1') b1[j]=1;
            else if(s[j]=='2') b2[j]=1;
            else if(s[j]=='3') b3[j]=1;
        }
        for(int j=1;j<=n;j++){
            if(s[j]=='0') continue;
            else if(s[j]=='1') bit[j]=bit[j]^(b2|b3);
            else if(s[j]=='2') bit[j]=bit[j]^(b1|b3);
            else if(s[j]=='3') bit[j]=bit[j]^(b1|b2|b3);
            bit[j][j]=0;
        }
    }
    int Ans=0;
    for(int j=1;j<=n;j++){
        Ans+=bit[j].count();
    }
    assert(Ans%2==0);
    Ans/=2;
    printf("%d\n",Ans);
    return 0;
}

T2

The essence of this problem is dp optimization. First, we consider how to check the dichotomy. We consider setting dp \(f_i \) to represent the first \ (I \) values. When each segment is greater than or equal to \ (0 \), how many segments can be divided at most. Naive dp is \ (n^2 \), and we consider that the whole transfer can be optimized with bit.

code:

#include<bits/stdc++.h>
#include<iostream>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N 200010
#define M number
using namespace std;

const int INF=0x3f3f3f3f;
const dd eps=1e-4;
const dd eps2=1e-10;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

template<typename T> inline T Max(T a,T b){return a<b?b:a;}

int n,a[N],k;

struct BIT{
    int p[N];
    inline void Init(int n){
        for(int i=1;i<=n;i++) p[i]=-1;
    }
    inline int lowbit(int x){return x&(-x);}
    inline void Add(int w,int x){
        for(int i=w;i<=n;i+=lowbit(i)) p[i]=Max(x,p[i]);
    }
    inline int GetMax(int w){
        int res=-INF;
        for(int i=w;i;i-=lowbit(i)) res=Max(res,p[i]);return res;
    }
}bit;

inline void Init(){
    read(n);read(k);
    for(int i=1;i<=n;i++) read(a[i]);
}

int f[N],d[N];
dd b[N],c[N],rk[N];

inline bool Check(dd mid){
    bit.Init(n);
    // printf("mid=%lf\n",mid);
    for(int i=1;i<=n;i++) b[i]=1.0*a[i]-mid;
    // printf("b:");for(int i=1;i<=n;i++) printf("%lf ",b[i]);puts("");
    for(int i=1;i<=n;i++) b[i]+=b[i-1];   
    for(int i=1;i<=n;i++) c[i]=b[i];
    sort(c+1,c+n+1);int len=unique(c+1,c+n+1)-c-1;
    // printf("c:");for(int i=1;i<=n;i++) printf("%lf ",b[i]);puts("");
    for(int i=1;i<=n;i++){
        int Rank=lower_bound(c+1,c+len+1,b[i])-c;
        rk[Rank]=b[i];d[i]=Rank;
    }
    // printf("d:");for(int i=1;i<=n;i++) printf("%d ",d[i]);puts("");
    for(int i=1;i<=n;i++){
        if(b[i]>=0) f[i]=1;
        else{f[i]=-1;continue;}
        int Ans=bit.GetMax(d[i]);
        f[i]=Max(f[i],Ans+1);
        bit.Add(d[i],f[i]);
    }
    // printf("f:");for(int i=1;i<=n;i++) printf("%d ",f[i]);puts("");
    return f[n]>=k;
}

inline void Solve(){
    dd l=1,r=100;
    while(r-l>eps){
        // printf("%lf\n",l);
        dd mid=(l+r)/2;
        if(Check(mid)) l=mid;
        else r=mid;
    }
    printf("%lf\n",l);
}

int main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    Init();Solve();return 0;
}

T3

This question is a conclusion question. We first consider such a thing, that is, we regard each edge as two "b". Here, in order to distinguish, we temporarily call it "b", and the following is the same. Then we consider such a thing. Now we dye b. We should dye the two b corresponding to each edge with color \ (0 \) or color \ (1 \), Then we consider how many medium dyeing schemes there are for a pipeline scheme.

We say that the two dyeing schemes are the same if and only if there is a pipe \ (x,y \) corresponding to it in the second dyeing scheme for a pipe \ (x,y \) of the first dyeing scheme, and the dyeing methods of the two pipes are the same.

Note that if a pipeline scheme does not have the same pipeline, the dyeing method is \ (2^{n-1} \). If there are \ (C \) pairs of the same pipeline, the dyeing method is \ (2^{n-1-c} \). This is because we consider that only one pair of pipelines are the same. If we exchange these two pipelines, the scheme will be calculated by \ (2 \) times.

We found that \ (2^{n-1-c} \) divided by \ (2^{n-1} \) is exactly the weight, so we just need to calculate the above dyeing scheme and divide the number of schemes by the power of \ (2^{n-1} \).

Then, if we directly count the dyeing scheme, it is not easy to calculate, so we consider what the dyeing scheme corresponds to. We consider putting the forced dyeing of \ (0 \) on the left and the forced dyeing of \ (1 \) on the right. Then we find that a dyeing method corresponds to a connection method of an edge. We consider the direct counting link method, The only limitation of this link is that two b's on one side cannot be connected.

At the same time, note that each point is independent, that is, the general link method should focus on each point, see how the edges adjacent to each point are connected, and then multiply the of all points.

For each point, it is equivalent to such a problem: there are \ (n \) pairs of points. Now we should match these \ (n \) pairs of points or do not match. There are some restrictions. The restrictions appear in the form of point pairs. Then a pair of points cannot match each other. Count the number of schemes in the East and west above.

Considering dp, let \ (f_{i,0/1/2} \) indicate that there are \ (I \) pairs and \ (0 / 1 / 2 \) single points, where there is a limit between these \ (I \) pairs. Ask the number of schemes that these points match or do not match.

For \ (f {I, 0} \), we consider how to match the last point of the last pair. First, this point may not match, so the scheme is \ (f {i-1,1} \), or matching, but only the points in the previous \ (i-1 \) pair of points can be selected to match. After matching, we throw away this pair of matched points and consider the scheme of the remaining points, This is done because the point on the match cannot match other points. From this, we can get:

\[f_{i,0}=f_{i-1,1}+f_{i-2,2}\times 2\times (i-1) \]

Similarly, we can also get:

\[f_{i,1}=f_{i,0}+f_{i-1,1}\times 2\times i\\ f_{i,2}=f_{i,1}+f_{i,0}+f_{i-1,2}\times 2\times i \]

After pretreatment dp, it can be transferred directly.

#include<iostream>
#include<cstdio>
#define ll long long
#define N 1000100
#define M number
using namespace std;

const int mod=1e9+7;

int f[N][3],n,ans=1,inv2=500000004,d[N];

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n-1;i++){
		int from,to;scanf("%d%d",&from,&to);d[from]++;d[to]++;
		ans=1ll*ans*inv2%mod;
	}
	f[0][0]=1;f[0][1]=1;f[0][2]=2;
	for(int i=1;i<=n;i++){
		f[i][0]=(f[i-1][1]+1ll*2*(i-1)*f[i-2][2]%mod)%mod;
		f[i][1]=(f[i][0]+1ll*f[i-1][1]*2*i%mod)%mod;
		f[i][2]=((f[i][1]+f[i][0])%mod+1ll*f[i-1][2]*2*i%mod)%mod;
	}
	for(int i=1;i<=n;i++) ans=1ll*ans*f[d[i]][0]%mod;
	printf("%d",ans);
	return 0;
} 

This question enlightens me that I can try to count similar but good cases, and then consider transformation.

Posted on Tue, 09 Nov 2021 19:38:12 -0500 by ghqwerty