nowcoder15254白兔的刁难

链接

点击跳转

单位根反演

其实就是一个公式,学过 F F T FFT 的人都能很容易的理解:

[ n k ] = 1 n i = 0 n 1 ω n i k [n|k] = \frac{1}{n} \sum_{i=0}^{n-1} \omega_n^{ik}

证明很简单,当 n k n|k n i k n|ik ,所以 ω n i k = ω n 0 = 1 \omega_{n}^{ik} = \omega_n^0 = 1 ,那么右边就等于 1 1
否则,就是一个等比数列求和, w n 0 w n n k 1 w n k = 0 \frac{w_{n}^{0}-w_n^{nk}}{1-w_n^k} = 0 ,右边等于 0 0

题解

根据 ( n i ) = ( n n i ) \binom{n}{i}=\binom{n}{n-i} ,以及异或运算的性质,可以得到以下结论:

n n 为奇数的时候, a n s = 0 ans=0

n n 为偶数的时候, a n s = a n s ( n / 2 m o d    k ) a n s ( ( n / 2 + k / 2 ) m o d    k ) ans = ans_{(n/2 \mod k)} \wedge ans_{ ((n/2+k/2) \mod k)}

其中 \wedge 表示异或

所以现在需要解决的问题就是对于某个给定的 t t ,求出 a n s t ans_t

直接硬写:

i = t n t ( n i + t ) [ k i ] = i = t n t ( n i + t ) j = 0 k 1 ω k i j = j = 0 k 1 i = t n t ( n i + t ) ω k i j \sum_{i=-t}^{n-t} \binom{n}{i+t} [k|i] \\ = \sum_{i=-t}^{n-t} \binom{n}{i+t} \sum_{j=0}^{k-1} \omega_{k}^{ij} \\ = \sum_{j=0}^{k-1} \sum_{i=-t}^{n-t} \binom{n}{i+t} \omega_{k}^{ij}

p = i + t p=i+t

j = 0 k 1 p = 0 n ( n p ) ω k j ( p t ) = j = 0 k 1 ω k j t p = 0 n ( n p ) ( ω k j ) p = j = 0 k 1 ω k j t ( 1 + ω k j ) n \sum_{j=0}^{k-1} \sum_{p=0}^n \binom{n}{p} \omega_{k}^{j(p-t)} \\ = \sum_{j=0}^{k-1} \omega_{k}^{-jt} \sum_{p=0}^n \binom{n}{p} (\omega_{k}^{j})^p \\ = \sum_{j=0}^{k-1} \omega_k^{-jt} (1+\omega_{k}^{j} )^n

所以直接枚举 j j 然后快速幂就行了

代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1500000
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
#define mod 998244353ll
ll n, k, wk[maxn];
ll fastpow(ll a, ll b)
{
    ll t(a%mod), ans(1);
    b=(b%(mod-1)+(mod-1))%(mod-1);
    for(;b;b>>=1,t=t*t%mod)if(b&1)(ans*=t)%=mod;
    return ans;
}
void pre()
{
    ll i;
    wk[0]=1, wk[1]=fastpow(3,(mod-1)/k);
    rep(i,2,k-1)wk[i]=wk[i-1]*wk[1]%mod;
}
ll calc(ll t)
{
    ll i, j, ans=0, mi=1, wkt=fastpow(wk[1],-t);
    rep(j,0,k-1)
    {
        ll tmp=mi*fastpow(1+wk[j],n)%mod;
        (ans+=tmp)%=mod;
        mi=mi*wkt%mod;
    }
    ans=ans*fastpow(k,mod-2)%mod;
    return (ans+mod)%mod;
}
char s[maxn];
ll tmp[maxn];
int main()
{
    ll i, j, len, t1=0, t2;
    scanf("%s%lld",s,&k); len=strlen(s);
    rep(i,0,len-1)(n=n*10+s[i]-0x30)%=(mod-1);
    if(s[len-1]%2==1){printf("0"); return 0;}
    if(k==1){printf("%lld",fastpow(2,n)); return 0;}
    rep(i,0,len-1)tmp[i]=s[i]-0x30;
    rep(i,0,len-1)
    {
        tmp[i+1]+=tmp[i]%2*10;
        tmp[i]/=2;
        t1=(t1*10+tmp[i])%k;
    }
    t2=(t1+k/2)%k;
    pre();
    printf("%lld",calc(t1)^calc(t2));
    return 0;
}
发布了948 篇原创文章 · 获赞 77 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/104457886