那些我还不太懂的题

NC14306 debug

图论,没题解,还没懂

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <map>

using namespace std;

const int MAXN = 260;
const int MAXM = 11000;
const int MAXS = 30;

map<string, int> h;

int n;
int m;
bool a[MAXN][MAXN];
bool ena[MAXN];
bool g[MAXN][MAXN];
bool chk[MAXN];
int mat[MAXN];
int q[MAXN];
int f[MAXN];

int getHash(string &s)
{
    if (h[s] == 0) return h[s] = (++n);
    else return h[s];
}

// 手写了一个FSA
void init()
{
    h.clear();
    string s;
    int cur = 1;
    bool d = true;
    n = 1;
    memset(a, false, sizeof(a));
    memset(ena, false, sizeof(ena));
    memset(f, 0xff, sizeof(f));
    memset(q, 0xff, sizeof(q));
    while (cin >> s && s != "END")
    {
        if (s == "STATEMENT")
        {
            if (!d) // 用来添加节点
            {
                a[cur][++n] = 1;
                cur = n;
            }
            ena[cur] = true; // 当前这个节点有statement要处理
        }
        else if (s == "GOTO")
        {
            cin >> s;
            a[cur][getHash(s)] = true;
            cur = 0;
        }
        else if (s == "IF")
        {
            cin >> s;
            cin >> s;
            a[cur][getHash(s)] = true;
            d = false;
        }
        else
        {
            int l = s.size();
            s = s.substr(0, l - 1);
            int v = getHash(s);
            a[cur][v] = true;
            cur = v;
            d = true;
        }
    }
    ena[1] = true; // ?
}

int cnt;

void dfs(int v)
{
    if (chk[v]) return;
    chk[v] = true;

    for (int i = 1; i <= n; ++i)
        if (ena[i] && a[v][i])
            dfs(i);
    q[++cnt] = v;
}

// 反图
void dfs2(int v)
{
    if (chk[v]) return;
    f[v] = cnt; // 连通分量的编号
    chk[v] = true;
    for (int i = 1; i <= n; ++i)
        if (ena[i] && a[i][v])
            dfs2(i);
}

// 类匈牙利...
bool dfs3(int v)
{
    for (int i = 1; i <= cnt; ++i)
        if (g[v][i] && !chk[i])
        {
            chk[i] = true;
            int tmp = mat[i];
            mat[i] = v;
            if (tmp == -1) return true;
            if (dfs3(tmp)) return true;
            mat[i] = tmp;
        }
    return false;
}

void solve()
{
    if (ena[0])
    {
        printf("-1\n");
        return;
    }


    int ne = 0;
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= n; ++j)
            for (int k = 1; k <= n; ++k)
                if (a[j][i] && a[i][k]) a[j][k] = 1; // 可达矩阵
        if (ena[i]) ++ne;
    }

    cnt = 0;
    memset(chk, 0, sizeof(chk));
    dfs(1);
    if (cnt != ne)
    {
        printf("-1\n");
        return;
    }
    // q:需要抵达的点
    memset(chk, 0, sizeof(chk));
    cnt = 0;
    // scc缩点图
    // kosaraju??
    for (int i = ne; i >= 1; --i)
        if (!chk[q[i]])
        {
            ++cnt;
            dfs2(q[i]);
        }

//     cout<<"cnt=="<<cnt<<endl;
    memset(g, 0, sizeof(g));
    for (int i = 1; i <= n; ++i)
        if (ena[i])
            for (int j = 1; j <= n; ++j)
                if (ena[j] && a[i][j] && f[i] != f[j])
                    g[f[i]][f[j]] = true;

    memset(mat, 0xff, sizeof(mat));
    int ans = cnt;
    for (int i = 1; i <= cnt; ++i)
    {
        memset(chk, 0, sizeof(chk)); if (dfs3(i)) --ans;
    }
    printf("%d\n", ans);
}

int main()
{
    int tt;
    cin >> tt;
    while (tt--)
    {
        init();
        solve();
    }
    return 0;
}


NC15075 导一导

首先推导就有点。。高数还是没学好
有n有i的卷积就能fft?
题解

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5;
int n, k, fac[N], ifac[N], a[N], b[N], bb[N], c[N];
const int mod = 998244353, G = 3;
int up, w[N], rev[N];
int fpw(int a, int b)
{
    int ans = 1;
    while(b)
    {
        if(b&1) ans = 1ll*ans*a%mod;
        a = 1ll*a*a%mod;
        b >>= 1;
    }
    return ans;
}
namespace poly
{
    void init(int n)
    {
        up = 1; int l = 0;
        while(up<=n) up <<= 1, l++;
        for(int i=0; i<up; i++) rev[i] = (rev[i>>1]>>1)|((i&1)<<(l-1));
        int wn = fpw(G, mod>>l); w[up>>1] = 1;
        for(int i=(up>>1)+1; i<up; i++) w[i] = 1ll*w[i-1]*wn%mod;
        for(int i=(up>>1)-1; i>=1; i--) w[i] = w[i<<1];
    }
    void clear(int *a, int n) { memset(a, 0, n<<2); }
    int getlen(int n) { return 1<<(32-__builtin_clz(n)); }
    inline void mul(int *a, int n, int x, int *b) { while(n--) *b++ = 1ll**a++*x%mod; }
    inline void dot(int *a, int *b, int n, int *c) { while(n--) *c++ = 1ll**a++**b++%mod; }
    void DFT(int *a, int l)
    {
        static unsigned long long tmp[N];
        int u = __builtin_ctz(up/l), t;
        for(int i=0; i<l; i++) tmp[i] = a[rev[i]>>u];
        for(int i=1; i^l; i<<=1)
            for(int j=0, d=i<<1; j^l; j+=d)
                for(int k=0; k<i; k++)
                    t = tmp[i|j|k]*w[i|k]%mod, tmp[i|j|k] = tmp[j|k]+mod-t, tmp[j|k] += t;
        for(int i=0; i<l; i++) a[i] = tmp[i]%mod;
    }
    void IDFT(int *a, int l)
    {
        reverse(a+1, a+l); DFT(a, l);
        mul(a, l, mod-mod/l, a);
    }
}
int comb(int n, int m)
{
    if(n<m||n<0||m<0) return 0;
    return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> k;
    poly::init(n+k);
    fac[0] = 1;
    for(int i=1; i<=n+k; i++) fac[i] = 1ll*fac[i-1]*i%mod;
    ifac[n+k] = fpw(fac[n+k], mod-2);
    for(int i=n+k-1; i>=0; i--) ifac[i] = 1ll*ifac[i+1]*(i+1)%mod;
    for(int i=1; i<=k; i++)
    {
        cin >> a[i];
        a[i] = 1ll*a[i]*ifac[i-1]%mod;
    }
    poly::DFT(a, up);
    for(int i=0; i<=n; i++)
    {
        b[i] = comb(n, i);
        if((n-i)%4>1) b[i] = mod - b[i];
        if(i&1) b[i] = mod - b[i];
    }
    for(int i=0; i<=n; i+=2) bb[i] = b[i];
    poly::DFT(bb, up);
    for(int i=0; i<up; i++) c[i] = 1ll*a[i]*bb[i]%mod;
    poly::IDFT(c, up);
    for(int i=1; i<=n+k; i++) cout << 1ll*c[i]*fac[i-1]%mod << " \n"[i==n+k];

    poly::clear(bb, up);
    for(int i=1; i<=n; i+=2) bb[i] = b[i];
    poly::DFT(bb, up);
    for(int i=0; i<up; i++) c[i] = 1ll*a[i]*bb[i]%mod;
    poly::IDFT(c, up);
    for(int i=1; i<=n+k; i++) cout << 1ll*c[i]*fac[i-1]%mod << " \n"[i==n+k];
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值