克拉克是一名人格分裂患者。某一天他变成一名数学家,在研究奇怪的东西。
他突然想算这么一个式子,给出 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
其实对于n来说,它的因子个数只有O(logn)个
所以一共k长度的那些,里面顶多也就能有logn次变化,所以先处理个组合数
然后可以考虑dp[i][j]=∑k|idp[k][j−1] , dp[i][1]=f[i]
表示对于i,如果有j次变化,那么肯定是从他的因子变过来的,并且是j−1次
这样就可以算出来如果用j层到达i的和,然后组合数计算有多少种情况就行了
只要在枚举i的时候,用logn的复杂度处理出所有的因子就行了,这就要线性筛了
代码:
#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;
}