zoukankan      html  css  js  c++  java
  • 题解 一个人的数论

    题目传送门

    Description

    给出

    [n=prod_{i=1}^{w}p_i^{a_i} ]

    求出:

    [sum_{i=1}^{n}[gcd(i,n)=1]i^d ]

    (dle 10^2,wle 10^3),答案对 (10^9+7) 取模。

    Solution

    [sum_{i=1}^{n} [gcd(i,n)=1]i^d ]

    [=sum_{i=1}^{n} (sum_{k|iwedge k|n}mu(k))i^d ]

    [=sum_{k|n} mu(k)k^d(sum_{i=1}^{frac{n}{k}}i^d) ]

    对于后面那一坨我们知道可以写成:

    [sum_{i=1}^{d+1} f_i(frac{n}{k})^i ]

    所以原式可以写成:

    [=sum_{k|n}mu(k)k^dsum_{i=1}^{d+1}f_i(frac{n}{k})^i ]

    [=sum_{i=1}^{d+1}f_in^isum_{k|n}mu(k)k^{d-i} ]

    我们可以观察到后面那一坨因为含有 (mu(k)),所以所有能够产生贡献的 (k) 的指数最大值不会超过 (1),所以直接 dp 即可。

    时间复杂度为 (Theta(d^3+dw))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define mod 1000000007
    #define MAXN 1005
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    int k,n,p[MAXN],a[MAXN],f[MAXN];
    int mul (int a,int b){return 1ll * a * b % mod;}
    int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
    int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
    int qkpow (int a,int b){
    	if (b < 0) b += mod - 1;
    	int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
    	return res;
    }
    int inv (int x){return qkpow (x,mod - 2);}
    
    int y[MAXN],mat[MAXN][MAXN];
    
    void Gauss  (){
    	int up = k + 1;
    	for (Int i = 1;i <= up;++ i){
    		for (Int j = 1;j <= up;++ j) mat[i][j] = qkpow (i,j); 
    		for (Int j = 1;j <= i;++ j) mat[i][up + 1] = add (mat[i][up + 1],qkpow (j,k));
    	}
    	for (Int i = 1;i <= up;++ i){
    		int pos = i;
    		for (Int j = i + 1;j <= up;++ j) if (mat[j][i] > mat[pos][i]) pos = j;
    		if (pos ^ i) swap (mat[i],mat[pos]);
    		for (Int j = i + 1;j <= up;++ j){
    			int det = mul (mat[j][i],inv (mat[i][i]));
    			for (Int k1 = i;k1 <= up + 1;++ k1) mat[j][k1] = dec (mat[j][k1],mul (det,mat[i][k1]));
    		}
    	}
    	for (Int i = up;i >= 1;-- i){
    		for (Int j = up;j > i;-- j) mat[i][up + 1] = dec (mat[i][up + 1],mul (f[j],mat[i][j]));
    		f[i] = mul (mat[i][up + 1],inv (mat[i][i]));
    	}
    } 
    
    int getans (int i,int now){
    	if (now > n) return 1;
    	return mul (dec (1,qkpow (p[now],k - i)),getans (i,now + 1));
    }
    
    signed main(){
    	read (k,n),Gauss ();
    	int get = 1;
    	for (Int i = 1;i <= n;++ i) read (p[i],a[i]),get = mul (get,qkpow (p[i],a[i]));
    	int ans = 0;for (Int i = 1;i <= k + 1;++ i) ans = add (ans,mul (f[i],mul (qkpow (get,i),getans (i,1))));
    	write (ans),putchar ('
    ');
    	return 0;
    }
    
  • 相关阅读:
    信用风险评分卡研究-第7章笔记
    信用风险评分卡研究-第6章笔记
    信用风险评分卡研究-第5章
    CSS3新特性
    H5相关知识点整理
    css3实现立体魔方效果
    后台管理系统基本布局
    react路由初探(2)
    react路由初探(1)
    将一个数组转化为需要的格式,来自react官网的商品列表示例
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/14355224.html
Copyright © 2011-2022 走看看