CSP2019题解

虽然CSP没过初赛没参加,但我还是想写一下题解

D1T1格雷码

按位考虑答案,第i位即为k xor [k/2]的第i位

#include<bits/stdc++.h>
using namespace std;
unsigned long long n,k;
int main()
{
    cin>>n>>k;
    while(n--)
    {
        putchar('0'+((k>>n)&1));
        if((k>>n)&1)k^=(1llu<<n)-1;
    }
}

D1T2括号树

简单树形DP,其实根本不用建边,直接O(n)循环树形DP即可

f[i]表示i到根节点路径的合法方案数

lst[i]表示上一个没匹配的位置

len[i]表示i到根的路径上匹配的括号串数

然后转移方程具体见code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+7;
int n,fa[N];
ll ans,f[N],lst[N],len[N];
char c[N];
int main()
{
    scanf("%d%s",&n,c+1);
    for(int i=2;i<=n;i++)scanf("%d",&fa[i]);
    for(int u=1,pre;u<=n;u++)
    {
        f[u]=f[pre=fa[u]],lst[u]=lst[pre];
        if(c[u]=='(')lst[u]=u;
        else if(c[u]==')'&&lst[u])len[u]=len[fa[lst[u]]]+1,lst[u]=lst[fa[lst[u]]],f[u]+=len[u];
        ans^=u*f[u];
    }
    printf("%lld",ans);
}

D1T3树上的数

什么神仙题我只会10分,先咕着

D2T1Emiya家今天的饭

感觉这题有一定难度,是有思维的DP,设f[i][j][k]表示前i行选j个节点,当前枚举列选k个节点方案数,复杂度O(mn^3),可得84分。

但这并不是我们的目标。

但我们只需要知道j,k的大小关系,即k>[j/2],即2k+n-j>n,n-j即为n行里没选的行数,然后具体转移方程可见代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200,M=3000,mod=998244353;
int n,m,ans=1,s[N],a[N][M],f[N][M];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)scanf("%d",&a[i][j]),s[i]=(s[i]+a[i][j])%mod;
        ans=1ll*ans*(s[i]+1)%mod;
    }
    ans=(ans+mod-1)%mod;
    for(int i=1;i<=m;i++)
    {
        memset(f,0,sizeof f);
        f[0][0]=1;
        for(int j=1;j<=n;j++)
        for(int k=0;k<=2*(j-1);k++)
        {
            f[j][k]=(f[j][k]+1ll*f[j-1][k]*(s[j]-a[j][i]+mod))%mod;
            f[j][k+1]=(f[j][k+1]+f[j-1][k])%mod;
            f[j][k+2]=(f[j][k+2]+1ll*f[j-1][k]*a[j][i])%mod;
        }
        for(int j=n+1;j<=2*n;j++)ans=(ans-f[n][j]+mod)%mod;
    }
    printf("%d",ans);
}

D2T2划分

先咕着

D2T3划分

咕咕咕

 

上一篇:Process类


下一篇:【CSP2019】Emiya 家今天的饭