BZOJ 3601 一个人的数论 ——莫比乌斯反演 高斯消元

http://www.cnblogs.com/jianglangcaijin/p/4033399.html

——lych_cys

我还是太菜了,考虑一个函数的值得时候,首先考虑是否积性函数,不行的话就强行展开,

如果是的话考虑最小因子的高次幂的情况

然后还要一点点猜想才行。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define md 1000000007
 
ll d,m;
ll h[110],a[110][110];
 
ll ksm(ll a,ll b)
{
    if (b<0) return ksm(ksm(a,md-2),-b);
    ll ret=1;
    while (b)
    {
        if (b&1) (ret*=a)%=md;
        (a*=a)%=md;
        b>>=1;
    }
    return ret;
}
 
ll pp[110],A[110];
 
void init()
{
    int i,j;
    for (i=0;i<=d+1;++i)
    {
        pp[i]=(ksm(i+1,d)+(i==0?0:pp[i-1]))%md;
        a[i][d+2]=pp[i];
        a[i][0]=1;
        ll pre=1;
        for (j=1;j<=d+1;++j)
        {
            (pre*=(i+1))%=md;
            a[i][j]=pre;
        }
    }
    int k;
    for (i=0;i<=d+1;++i)
    {
        for (j=i;j<=d+1;++j) if (a[j][i]) break;
        if (i!=j) for (k=0;k<=d+2;++k) swap(a[i][k],a[j][k]);
        for (j=0;j<=d+1;++j) if (j!=i&&a[j][i])
        {
            ll tmp=(a[j][i]*ksm(a[i][i],-1))%md;
            for (k=0;k<=d+2;++k) (a[j][k]-=tmp*a[i][k])%=md;
        }
    }
    for (i=0;i<=d+1;++i) A[i]=(a[i][d+2]*ksm(a[i][i],-1))%md;
}
 
ll dd[1220][3];
 
int main()
{
    scanf("%lld%lld",&d,&m);
    init();
    F(i,1,m) scanf("%lld%lld",&dd[i][0],&dd[i][1]);
    ll ans=0;
    F(i,0,d+1)
    {
        ll tmp=1;
        F(j,1,m)
        {
            tmp=tmp*ksm(dd[j][0],(ll)dd[j][1]*i)%md;
            tmp=tmp*(1-ksm(dd[j][0],d-i))%md;
        }
        ans+=A[i]*tmp%md;
        ans%=md;
    }
    ((ans%=md)+=md)%=md;
    printf("%lld\n",ans);
}

  

posted @ 2017-04-05 12:04  SfailSth  阅读(234)  评论(0编辑  收藏  举报