2020HDU多校第五场By Rynar

1001.Tetrahedron

思路:可以叉积,余弦定理+1/2absin,海伦公式,计算得1/h^2=1/a^2+1/b^2+1/c^2,a为1-n,所以期望为3*(1+1/2^2+...+1/n^2)/n

typedef long long ll;
const int N=6e6+10;
const int mod=998244353;
#define int ll
int n,m,k;
int inv[N],f[N];
void get_inv(int n,int p){
    inv[0]=inv[1]=1;
    for (int i=2;i<=n;i++){
        inv[i]=inv[p%i]*(p-p/i)%p;
    }   
}
signed main(){
    int T;
    get_inv(N-1,mod);
    int t=0;
    for (int i=1;i

1002.Funny String

1003.Boring Game

模拟写的不太好

const int N=5e5+10;
int n,m,k,p;
int a[N],c[N],nx[N];
int b[210][2000];
void dfs(int k,int n){
    if (n==p)return;
    for (int i=0;i=1;j--){
                    b[j][i]=++be;
                }
            }
        }
        for (int i=n;i>=1;i--){
            for (int j=1;j<=p;j++){
                if (j&1)printf("%d ",a[b[i][j]*2]);
                else printf("%d ",a[b[i][j]*2-1]);
            }
            for (int j=1;j<=p;j++){
                if (j&1)printf("%d",a[b[i][j]*2-1]);
                else printf("%d",a[b[i][j]*2]);
                if (i!=1||j!=p)printf(" ");
            }
        }
        puts("");
    }
    return 0;
}

1004.Expression

1005.Array Repairing

1006.Alice and Bob

1007.Tree

//写的也不太好
思路:树形dp,要考虑的情况挺多的,dp[i][0]记录子树无>k的度的最大权值和,dp[i][0]记录子树存在一个>k的度的最大权值和。
当前x子树<=k-1时,dp[x][0]为dp[i][0]的和,dp[x][1]为一个dp[i][1]和其他dp[i][0]
当前x子树>k-1时,dp[x][0]为前k-1大的dp[i][0]的和,dp[x][1]为全部dp[i][0]的和或k-2个dp[i][0]和一个dp[i][1]的最大和
另外,dfs每搜到一个点要处理两次以上操作,一次记录到dp内,代表这个点不是根,k=k-1,另一次不记录到dp内,代表这个点是根,k=k,更新ans=max(ans,处理出的不记录到dp内的答案)

typedef long long ll;
const int N=2e5+10;
#define int ll
typedef pair pii;
int n,m,k,p;
int dp[N][2];
int ans,rt;
vectorv[N];
void dfs(int x,int fa){
    int cnt=0;
    for (pii i:v[x]){
        if (i.first==fa)continue;
        dfs(i.first,x);
        dp[i.first][0]+=i.second;
        dp[i.first][1]+=i.second;
        cnt++;
    }
    k--;
    if (cnt>k){
        priority_queue  q;
        int r=0;
        for (pii i:v[x]){
            if (i.first==fa)continue;
            q.push({dp[i.first][0],i.first});
            r+=dp[i.first][0];
        }
        dp[x][1]=max(dp[x][1],r);
        int cnt1=0,mx=0,e=0;
        while (!q.empty()){
            cnt1++;
            if (cnt1<=k)dp[x][0]+=q.top().first;
            if (cnt1==k)e=q.top().first;
            q.pop();
        }
        for (pii i:v[x]){
            if (i.first==fa)continue;
            q.push({dp[i.first][0],i.first});
        }
        cnt1=0;
        while (!q.empty()){
            cnt1++;
            int t=q.top().second;
            if (cnt1<=k){
                mx=max(mx,dp[x][0]-dp[t][0]+dp[t][1]);
            }
            else{
                mx=max(mx,dp[x][0]-e+dp[t][1]);
            }
            q.pop();
        }
        dp[x][1]=max(mx,dp[x][1]);
    }
    else{
        int mx=0;
        for (pii i:v[x]){
            if (i.first==fa)continue;
            dp[x][0]+=dp[i.first][0];
            mx=max(mx,dp[i.first][1]-dp[i.first][0]);
        }
        dp[x][1]=max(dp[x][1],dp[x][0]+mx);
    }
    ans=max(dp[x][1],ans);
    k++;
    if (cnt>k){
        priority_queue  q;
        for (pii i:v[x]){
            if (i.first==fa)continue;
            q.push({dp[i.first][0],i.first});
        }
        int cnt1=0,mx=0,e=0,u=0;
        while (!q.empty()){
            cnt1++;
            if (cnt1<=k)u+=q.top().first;
            if (cnt1==k)e=q.top().first;
            q.pop();
        }
        for (pii i:v[x]){
            if (i.first==fa)continue;
            q.push({dp[i.first][0],i.first});
        }
        cnt1=0;
        while (!q.empty()){
            cnt1++;
            int t=q.top().second;
            if (cnt1<=k){
                mx=max(mx,u-dp[t][0]+dp[t][1]);
            }
            else{
                mx=max(mx,u-e+dp[t][1]);
            }
            q.pop();
        }
        ans=max(mx,ans);
    }
    else{
        int mx=0,u=0;
        for (pii i:v[x]){
            if (i.first==fa)continue;
            u+=dp[i.first][0];
            mx=max(mx,dp[i.first][1]-dp[i.first][0]);
        }
        ans=max(ans,u+mx);
    }
}
signed main(){
    int T,x,y,z;
    scanf("%lld",&T);
    while (T--){
        scanf("%lld%lld",&n,&k);
        ans=0;
        for (int i=0;i<=n;i++){
            v[i].clear();dp[i][0]=dp[i][1]=0;
        }
        for (int i=1;i1){
            dfs(1,-1);
            printf("%lld\n",ans);
        }
        else if (k==0){
            puts("0");
        }
        else if (k==1){
            int mx=0;
            for (int i=1;i<=n;i++){
                int r=0;
                for (pii j:v[i]){
                    r+=j.second;
                }
                mx=max(mx,r);
            }
            printf("%lld\n",mx);
        }
    }
    return 0;
}

1008.Set2

思路:概率dp
见代码理解图
2020HDU多校第五场By Rynar_第1张图片
2020HDU多校第五场By Rynar_第2张图片
去除前面i-j个数中的一个可以变为
2020HDU多校第五场By Rynar_第3张图片
去除后面的j-1个数中的一个可以变为
2020HDU多校第五场By Rynar_第4张图片

typedef long long ll;
const int N=5e6+10;
const int mod=998244353;
#define int ll
int n,m,k;
int inv[N],dp[N];
void get_inv(int n,int p){
    inv[0]=inv[1]=1;
    for (int i=2;i<=n;i++){
        inv[i]=inv[p%i]*(p-p/i)%p;
    }
}
signed main(){
    int T;
    get_inv(N-1,mod);
    scanf("%lld",&T);
    while (T--){
        scanf("%lld%lld",&n,&k);
        int p=n%(k+1);
        for (int i=0;i<=n;i++)dp[i]=1;//记录倒数第i个数能留下来的概率
        for (int i=p+1;i<=n;i++){//当前还存在的数的数量,从最后只存在p个数的状态往前推
            dp[i]=0;//新的数概率为0
            if ((n-i)%(k+1)==0) continue;//这个数是第一个操作去除的
            for (int j=i;j>=1;j--){
                (dp[j]=dp[j]*(i-j)%mod*inv[i]%mod+dp[j-1]*(j-1)%mod*inv[i]%mod)%=mod;//如上图
            }
        }
        for (int i=n;i>=1;i--){
            if (i!=n)printf(" ");
            printf("%lld",dp[i]);
        }
        puts("");
    }
    return 0;
}

1009.Paperfolding

思路:横着折x次,竖着折y次,剪开纸片数为(1+2^x)*(1+2^y)=2^(x+y)+2^x+2^y+1=2^n+1+2*(0Cn*2^0+...+nCn*2^n)/2^n=(二项式定理)2^n+1+2*3^n/2^n

typedef long long ll;
const int N=1e6+10;
const int mod=998244353;
#define int ll
int n,m,k;
int qpow(int x,int y){
    int ans=1;
    while (y){
        if (y&1)ans=ans*x%mod;
        y>>=1;x=x*x%mod;
    }
    return ans;
}
signed main(){
    int T;
    scanf("%lld",&T);
    while (T--){
        scanf("%lld",&n);
        n%=mod-1;
        int m=(qpow(3,n)*qpow(qpow(2,mod-2),n))%mod;
        m=m*2%mod;
        m=(qpow(2,n)+1+m)%mod;
        printf("%lld\n",m);
    }
    return 0;
}

1010.Function

1011.Exam

1012.Set1

思路:2020HDU多校第五场By Rynar_第5张图片

typedef long long ll;
const int N=5e6+10;
const int mod=998244353;
#define int ll
int n;
int inv[N],x[N],y[N],y2[N];
int cnt[N];
void get_inv(int n,int p){
    inv[0]=inv[1]=1;
    for (int i=2;i<=n;i++){
        inv[i]=inv[p%i]*(p-p/i)%p;
    }   
}
int qpow(int x,int y){
    int ans=1;
    while (y){
        if (y&1)ans=ans*x%mod;
        y>>=1;x=x*x%mod;
    }
    return ans;
}
int C(int n,int m){
    return x[n]*y[m]%mod*y[n-m]%mod;
}
signed main(){
    int T;
    get_inv(N-1,mod);
    x[0]=y[0]=y2[0]=1;
    for (int i=1;i

1013.An Easy Matrix Problem

你可能感兴趣的:(2020HDU多校第五场By Rynar)