Tennis Game
通过排列组合解决问题。
首先两组不同素数的乘积,是互不相同的。这应该算是唯一分解定理的逆运用了。
然后是,输入中的素数,任意组合,就是n的因数,而且不会重复。
然后只需要知道,每个质数在所有组合中出现了几次就行了。
如果某一个质数再输入中只出现了一次,那么它在组合中出现的次数就应该是其他所有质数在输入中出现次数加一的乘积。
如果某一个质数x在输入中出现了多次,那么便只需把x,x*x, x*x*x等数暂且当做一个输入中的数来计算就是了,然后相加;容易知道这样的话,相当于x出现次数为1,2,3,4...... 于是用等差数列求和的结果乘上上一条说的结果就行了。
之后便可以将质数的(组合中出现的次数)次方 全部乘起来就行了。
1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 #include<stack> 5 #include<queue> 6 #include<map> 7 #include<set> 8 #include<cstdio> 9 #include<cstring> 10 #include<cmath> 11 #include<ctime> 12 #define fuck(x) cout<<#x<<" = "<<x<<endl; 13 #define ls (t<<1) 14 #define rs ((t<<1)+1) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 1000086; 19 const int inf = 2.1e9; 20 const ll Inf = 999999999999999999; 21 const int mod = 1000000007; 22 const double eps = 1e-6; 23 const double pi = acos(-1); 24 ll num[maxn],res[maxn]; 25 ll l[maxn],r[maxn]; 26 27 ll q_pow(ll a,ll b) 28 { 29 ll ans=1; 30 while(b){ 31 if(b&1){ans*=a;ans%=mod;} 32 a*=a;a%=mod; 33 b>>=1; 34 } 35 return ans; 36 } 37 38 int main() 39 { 40 int m; 41 scanf("%d",&m); 42 int maxx = 0; 43 for(int i=1;i<=m;i++){ 44 int x; 45 scanf("%d",&x); 46 maxx=max(maxx,x); 47 num[x]++; 48 } 49 int t=0; 50 for(int i=1;i<=maxx;i++){ 51 if(num[i]){ 52 t++; 53 res[t]=num[i]; 54 num[t]=i; 55 } 56 } 57 l[0]=1; 58 for(int i=1;i<=t;i++){ 59 l[i]=(1+res[i])*l[i-1]; 60 l[i]%=(mod-1); 61 } 62 r[t+1]=1; 63 for(int i=t;i>=1;i--){ 64 r[i]=(res[i]+1)*r[i+1]; 65 r[i]%=(mod-1); 66 } 67 68 ll ans=1; 69 for(int i=1;i<=t;i++){ 70 ll d = (l[i-1])*(r[i+1]); 71 d%=(mod-1); 72 73 ll p = res[i]*(res[i]+1)/2; 74 p%=(mod-1); 75 76 d = d*p; 77 d%=(mod-1); 78 ans*=q_pow(num[i],d); 79 ans%=mod; 80 } 81 printf("%lld",ans); 82 83 return 0; 84 }