ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

abc256 G - Black and White Stones

2022-07-07 12:34:22  阅读:137  来源: 互联网

标签:Stones Md int res ll abc256 White rep mod


题意:

边长为 \(d\) 的正 \(n\) 边形,每条边上等距分布着 \(d+1\) 个点(包括两个端点)。现要把每个点染成黑/白色,要求每条边上的白点数相同,问方案数取模

要考虑顺序,即旋转对称/轴对称的算不同方案。

\(3\le n\le 1e12,1\le d\le 1e4\)

\(n=3,d=2\) 的示意图:

Figure

思路:

从 \(0\) 到 \(d+1\) 枚举每条边上的白点数 \(k\),然后 dp 求方案数

\(dp(fr,i,j)\) 表示第一个点是 \(fr\) 色,处理到第 \(i\) 条边,第 \(i\) 条边的终点是 \(j\) 色。暴力求 \(g(i)=f(0,i,0)+g(1,i,1)\) 的前几项然后BM加速求 \(g(n)\)

当然黑白是对称的,求 \(g(i)=2f(0,i,0)\) 即可

const int mod = 998244353;

ll qmi(ll a, ll b) {
    ll res = 1; a %= mod;
    for(; b; b >>= 1) {
        if(b&1) res = res * a % mod;
        a = a * a % mod;
    }
    return res;
}

namespace linear_seq {
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define SZ(x) ((int)(x).size())
    typedef vector<ll> VI;
    const int N=10010;
    ll res[N],base[N],_c[N],_md[N];

    vector<int> Md;
    void mul(ll *a,ll *b,int k) {
        rep(i,0,k+k) _c[i]=0;
        rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
        for (int i=k+k-1;i>=k;i--) if (_c[i])
            rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
        rep(i,0,k) a[i]=_c[i];
    }
    int solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
        ll ans=0,pnt=0;
        int k=SZ(a);
        assert(SZ(a)==SZ(b));
        rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
        Md.clear();
        rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
        rep(i,0,k) res[i]=base[i]=0;
        res[0]=1;
        while ((1ll<<pnt)<=n) pnt++;
        for (int p=pnt;p>=0;p--) {
            mul(res,res,k);
            if ((n>>p)&1) {
                for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
                rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
            }
        }
        rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
        if (ans<0) ans+=mod;
        return ans;
    }
    VI BM(VI s) {
        VI C(1,1),B(1,1);
        int L=0,m=1,b=1;
        rep(n,0,SZ(s)) {
            ll d=0;
            rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
            if (d==0) ++m;
            else if (2*L<=n) {
                VI T=C;
                ll c=mod-d*qmi(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                L=n+1-L; B=T; b=d; m=1;
            } else {
                ll c=mod-d*qmi(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                ++m;
            }
        }
        return C;
    }
    int gao(VI a,ll n) {
        VI c=BM(a);
        c.erase(c.begin());
        rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
        return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
    }
};

const int N = 1e5 + 3;
ll jie[N], jieni[N]; void init() {
    jie[0] = 1; for(int i = 1; i < N; i++)
        jie[i] = jie[i-1] * i % mod;
    jieni[N-1] = qmi(jie[N-1], mod-2);
    for(int i = N-1; i; i--) jieni[i-1] = jieni[i]*i%mod;
}
ll C(ll n, ll k) {
    if(k > n || k < 0) return 0;
    return jie[n] * jieni[k] % mod * jieni[n-k] % mod;
}
ll add(ll a, ll b) { return ((a+b)%mod+mod)%mod; }

ll n, d, f[23][2], g[23];

void sol() {
    cin >> n >> d;
    ll ans = 0;
    for(int k = 0; k <= d + 1; k++) {
        memset(f, 0, sizeof f), f[0][0] = 1; //初值
        for(int i = 1; i <= 20; i++) { //dp
            for(int a = 0; a <= 1; a++) //这条边的末尾
            for(int b = 0; b <= 1; b++) //上条边的末尾
                f[i][a] = add(f[i][a], f[i-1][b] * C(d-1, k-a-b) % mod);
            g[i] = add(f[i][0], f[i][0]); //黑色开头也一样
        }
        ans = add(ans, linear_seq::gao(vector<ll>(g+1,g+20), n-1));
    }
    cout << ans;
}

标签:Stones,Md,int,res,ll,abc256,White,rep,mod
来源: https://www.cnblogs.com/wushansinger/p/16454228.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有