HDU 5528 Count a * b (積性函式)*
阿新 • • 發佈:2018-12-13
#include<bits/stdc++.h> using namespace std; #define debug puts("YES"); #define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++) #define read(x,y) scanf("%d%d",&x,&y) #define ll unsigned long long #define lrt int l,int r,int rt #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define root l,r,rt const int maxn =1e5+5; const int mod=1e9+7; ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x) if(y&1) t=t*x; return t;} ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} ll n; /* 題目大意:計算式子,g(n)=sigma m|n f(m), 其中f函式代表著,在m*m方格中,i*j%m!=0的數量。 首先我們把f函式簡單處理下,m*m-二維sigma [i*j%m==0], 不難轉換,後面的二維sigma 可以變換成:一維sigma gcd(i,m), 這個式子只要帶有gcd就很經典,列舉gcd就行, 變化成euler*I(I為恆等函式,euler為尤拉函式), euler =I*miu,所以最後如果再sigma 一下: 答案直接就是:n*d(n)(d(n)為約數個數). sigma m|n m*m-n*d(n)。 */ ///篩素數 int prim[maxn],tot=0; int vis[maxn]; void sieve() { for(int i=2;i<maxn;i++) { if(vis[i]==0) prim[tot++]=i; for(int j=0;j<tot;j++) { if(1LL*i*prim[j]>=maxn) break; int k=i*prim[j];vis[k]=1; if(i%prim[j]==0) break; } } } int main() { sieve(); int t;scanf("%d",&t); while(t--) { scanf("%lld",&n); ll m=1,tp=n,cnt; for(int i=0;prim[i]*prim[i]<=n;i++) { if(n%prim[i]==0) { cnt=0; while(n%prim[i]==0) n/=prim[i],cnt++; ///m*=(powmod(prim[i],2*cnt+2)-1)/(prim[i]*prim[i]-1); ///上一行WA,可能會越界 ll f=1,s=1; for(int j=0;j<cnt;j++) s*=prim[i],f+=s*s; m*=f,tp*=(cnt+1); } } if(n>1) m*=(n*n+1),tp<<=1; printf("%llu\n",(m-tp)); } return 0; } /* 1388887464341212650 */