LOJ6358 前夕

上来4的倍数又要交集恰好 单位根反演+二项式反演定了(

具体推柿子放下面了qwq

$g(n) = \sum_{i=n}^N f(i) \binom{i}{n} \\g(n) = \binom{N}{n} (2^{2^{N-n}}-1) \\f(n) = \sum_{i=n}^N \binom{i}{n} (-1)^{n-i} g(i) \\ ans = \sum_{n=0}^N [n\%4==0] f(n) \\ans= \sum_{n=0}^N \sum_{j=0}^3 w_4^{nj} f(n) \\ans= \sum_{n=0}^N \sum_{i=n}^N \sum_{j=0}^3 w_4^{nj}(-1)^{i-n}g(i)\binom{i}{n}\\ans= \sum_{i=0}^N (-1)^i g(i) \sum_{n=0}^i \sum_{j=0}^3 w_4^{nj} (-1)^n \binom{i}{n}\\ans= \sum_{i=0}^N (-1)^i g(i) \sum_{j=0}^3 (-w_4^{j}+1)^i$

里面那个-1是为了方便处理空集(不然空集可能加上可能被容斥掉了x)

然后憨憨hywn发现自己不会快速求$2^{2^{N-n}}$ 被大爹suncb教了一发...直接每次平方就好了...我可能是个sbx

于是就做完啦

(第一次推完这么长柿子好感动)

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
#define mdn 998244353
#define G 3
#define inv4 748683265ll
using namespace std;
int read()
{
    int s=0,t=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')    t=-1; ch=getchar();}
    while(ch>='0' && ch<='9')    s=s*10+ch-'0',ch=getchar();
    return s*t;
}
int ksm(int bs,int mi)
{
    int ans=1;
    while(mi)
    {
        if(mi&1)    ans=1ll*ans*bs%mdn;
        bs=1ll*bs*bs%mdn; mi>>=1; 
    }
    return ans;
}
#define N 10000001
int w[4][2],fac[N],inv[N],g[N];
int C(int n,int m){return n<m?0:1ll*fac[n]*inv[m]%mdn*inv[n-m]%mdn;}
int main()
{
    int n=read(); int Wn=ksm(G,(mdn-1)/4); int ans=0;
    for(int i=0;i<4;i++)    w[i][0]=1;
    for(int i=0;i<4;i++)    w[i][1]=(-ksm(Wn,i)+1+mdn)%mdn;
    fac[0]=1;
    for(int i=1;i<=n;i++)    fac[i]=1ll*fac[i-1]*i%mdn;
    inv[n]=ksm(fac[n],mdn-2);
    for(int i=n;i;i--)     inv[i-1]=1ll*inv[i]*i%mdn;
    g[n]=2;
    for(int i=n;i;i--)    g[i-1]=1ll*g[i]*g[i]%mdn;
    for(int i=0;i<=n;i++)
    {
        int val=0;
        for(int j=0;j<4;j++)
            (val+=w[j][0])%=mdn,w[j][0]=1ll*w[j][0]*w[j][1]%mdn;
        (ans+=1ll*(g[i]-1)*C(n,i)%mdn*(i&1?mdn-1:1)%mdn*val%mdn*inv4%mdn)%=mdn;
    }
    printf("%d\n",ans+1);
    return 0;
}
View Code
posted @ 2019-12-15 20:21  寒雨微凝  阅读(259)  评论(0编辑  收藏  举报