51nod 1769 Clarke and math2(线性筛+dp)

克拉克是一名人格分裂患者。某一天他变成一名数学家,在研究奇怪的东西。
他突然想算这么一个式子,给出 f(i),1≤i≤n ,要求算
g(i)=∑i1∣i∑i2∣i1∑i3∣i2⋯∑ik∣ik−1f(ik) mod 1000000007 (1≤i≤n,ij∈N+)
∣ 是整除的意思,比如 i1=5,i2=10则i1∣i2

样例解释:

g(i) = sum(i1 | i) sum(i2 | i1) sum(i3 | i2) f(i3)

我们来看g(2)

当i1=1, i2=1, i3=1时累加一个f(1)
当i1=2, i2=1, i3=1时累加一个f(1)
当i1=2, i2=2, i3=1时累加一个f(1)
当i1=2, i2=2, i3=2时累加一个f(2)

所以g(2)=f(1)+f(1)+f(1)+f(2)=9
Input
第一行为两个整数n, k(1 ≤ n ≤ 500000, 1 ≤ k ≤ 10^1000000)。
接下来一行n个整数,第i个整数代表f(i), 0 ≤ f(i) < 10^9+7。
Output
输出一行n个数,第i个表示g(i)。
Input示例
23 3
2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
Output示例
2 9 9 24 9 39 9 50 24 39 9 102 9 39 39 90 9 102 9 102 39 39 9



GG
nO(logn)
klogn
dp[i][j]=k|idp[k][j1] dp[i][1]=f[i]
ijj1
ji
ilogn线


代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;
#define   MAX           500005
#define   MAXN          1000005
#define   maxnode       105
#define   sigma_size    30
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
const double inf   = 1e18;
const double eps   = 1e-6;
const LL     mod   = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x) {
      char c;
      while((c=getchar())<'0' || c>'9');
      x=c-'0';
      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
 }
/*****************************************************/

char s[MAX*2];
int f[MAX];
LL C[25];
int dp[MAX][25];
LL qpow(LL a,LL n){
    LL ans=1;
    while(n){
        if(n&1) ans=ans*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans;
}

LL cal(LL n,int m){
    LL ans=1;
    for(int i=0;ifor(int i=0;i1,mod-2)%mod;
    return ans;
}
bool prime[MAX];
int pr[MAX];
int tot;
int h[MAX];
vector v;
int divi[MAX];
int num;
void init(){
    mem(prime,0);tot=0;
    for(int i=2;iif(!prime[i]){
            pr[tot++]=i;
            h[i]=i;
        }
        for(int j=0;j1;
            if(i%pr[j]==0){
                h[pr[j]*i]=h[i];
                break;
            }
            h[pr[j]*i]=pr[j];
        }
    }
}

void dfs(int x,int y){
    if(x==v.size()){
        divi[num++]=y;
        return;
    }
    for(int i=0;i<=v[x].second;i++){
        dfs(x+1,y);
        y*=v[x].first;
    }
}

int main(){
    //freopen("in.txt","r",stdin);
    int n;
    init();
    scanf("%d%s",&n,s);
    for(int i=1;i<=n;i++) RI(f[i]);
    int len=strlen(s);
    LL x=0;
    for(int i=0;i10+(s[i]-'0');
        x%=mod;
    }
    for(int i=0;i<=20;i++) C[i]=cal(x,i);
    for(int i=1;i<=n;i++){
        int k=i;
        int ans=0;
        v.clear();
        while(k>1){
            int xx=h[k];
            int j=0;
            while(h[k]==xx){
                k/=xx;
                j++;
            }
            v.push_back(mk(xx,j));
        }
        num=0;
        dfs(0,1);
        num--;
        dp[i][1]=f[i];
        for(int j=1;j<20;j++){
            dp[i][j+1]=0;
            for(int k=0;k1]+=dp[divi[k]][j];
                if(dp[i][j+1]>=mod) dp[i][j+1]-=mod;
            }
        }
        for(int j=1;j<=20;j++){
            if(dp[i][j]){
                ans+=C[j-1]*dp[i][j]%mod;
                if(ans>=mod) ans-=mod;
            }
        } 
        int sum=ans;
        printf("%d",sum);
        if(i==n) printf("\n");
        else printf(" ");
    }
    return 0;
}

你可能感兴趣的:(51nod 1769 Clarke and math2(线性筛+dp))