1. 程式人生 > >hdu6053 多校第二場(莫比烏斯函式,列舉)

hdu6053 多校第二場(莫比烏斯函式,列舉)

之前不知道莫比烏斯反演,看了一波,然後有些許理解,這個題其實就是使用了莫比烏斯函式U的定義,詳細的解題報告這裡說的比較清楚

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
#define clr(x) memset(x,0,sizeof(x))
using namespace std; #define LL long long const int N = 100005; const int MOD = 1e9+7; bool vis[N]; int U[N]; int prime[N]; int cnt; void GetMU() { memset(vis,0,sizeof(vis)); U[1] = 1; cnt = 0; for(int i=2; i<N; i++) { if(!vis[i]) { prime[cnt++] = i; U[i] = -1
; } for(int j=0; j<cnt&&i*prime[j]<N; j++) { vis[i*prime[j]] = 1; if(i%prime[j]) U[i*prime[j]] = -U[i]; else { U[i*prime[j]] = 0; break; } } } } LL quickPow(LL a,LL b) { LL ans = 1
; while(b) { if(b&1) { ans *= a; ans %= MOD; } a*=a; a %= MOD; b>>=1; } return ans; } int dat[N]; int mi,ma; int main() { int t; GetMU(); scanf("%d",&t); int _case = 0; while(t--) { int n; mi = 9999999; ma = 0; scanf("%d",&n); clr(dat); for(int i = 0;i<n;i++) { int temp; scanf("%d",&temp); dat[temp]++; mi = min(mi,temp); ma = max(ma,temp); } for(int i = 1;i<=ma;i++)dat[i] += dat[i-1]; LL ans = 0; for(int i = 2;i<=mi;i++) { LL cur = -U[i]; for(int j = 1;j*i<=ma;j++) { int l = i*j; int r = min(i*j+i-1,ma); cur = cur*(quickPow(j,dat[r]-dat[l-1]))%MOD; } ans += cur; ans = (ans+MOD)%MOD; } printf("Case #%d: %lld\n",++_case,ans); } return 0; }