1. 程式人生 > >『ZOJ 3547』The Boss on Mars (容斥原理)

『ZOJ 3547』The Boss on Mars (容斥原理)

ostream idt employee ant mars pri mes because reason

傳送門戳這裏qwq

題目描述

On Mars, there is a huge company called ACM (A huge Company on Mars), and it’s owned by a younger boss.

Due to no moons around Mars, the employees can only get the salaries per-year. There are nemployees in ACM, and it’s time for them to get salaries from their boss. All employees are numbered from 1 to n

. With the unknown reasons, if the employee’s work number is k, he can get k^4 Mars dollars this year. So the employees working for the ACM are very rich.

Because the number of employees is so large that the boss of ACM must distribute too much money, he wants to fire the people whose work number is co-prime with n

next year. Now the boss wants to know how much he will save after the dismissal.

題目翻譯(XJH版本)

又若幹年之後,XJH成為了一個上市企業的老板,然而是一個摳門的老板(XJH:???)。

XJH的公司裏面有n個員工,編號是1~n。每個人的工資是自己編號的四次方,例如,編號為5的員工,工資就是54=625。 (員工1:???)

然而,XJH覺得工資發的太多了,需要裁員。於是,決定把所有編號和自己互質的員工都裁掉(XJH的編號顯然是n,肥水不流外人田)。 現在,問:XJH裁員之後能省多少錢?

解題思路

我們直接一上來就能看出一種O(n)的做法,那就是一個數一個數的枚舉,如果這個數沒有被訪問過並且和n是互質的,那麽這個數的次方都與n互質,計算的過程中順便把vis標記一下,標準的O(n),標準的TLE。。。。

我們不妨轉換一下思路:我們不妨求所有於所有與n不互質的數的四次方之和,再用 ∑n^4 把它減掉,也能得到所有的結果。並且,1e8以內的數的質因子個數很少,所以這樣應該不會超時,但是還有一個難點——如何推出四次方求和公式?

我們退而求其次,不妨先求出更低次的求和公式:

技術分享圖片

這樣,我們就可以推出二次求和公式,以此類推,我們就可以得到4次求和公式:

技術分享圖片

既然有除,又有膜,所以我們就要用到逆元了。

比如n與3不互質,那和6,9,12,15也就不互質,那麽我們將這個數列除以3,就得到差為1的等差數列,這樣我們就很容易求了。運用容斥原理,二進制枚舉就可以了。

代碼

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define ll long long
 6 using namespace std;
 7 const int maxn=10050;
 8 const ll MOD=1e9+7;
 9 const ll ni=233333335;
10 bool pri[maxn];
11 ll p[maxn],num[maxn];
12 ll T,n,cnt=0,tot=0,ans;
13 inline void ini(){
14     pri[1]=0;
15     for(register int i=2;i<maxn;i++){
16         if(pri[i]){
17             p[++cnt]=i;
18             for(register int j=2;j*i<maxn;j++)pri[i*j]=0;
19         }
20     }
21 }
22 inline ll ksm(ll a,ll b){
23     ll c=1;
24     while(b){
25         if(b&1)c=c*a%MOD;
26         a=a*a%MOD,b>>=1;
27     }
28     return c%MOD;
29 }
30 inline ll calc(ll x){
31     ll y=x%MOD;
32     y=y*(x+1)%MOD;
33     y=y*(2*x+1)%MOD;
34     y=y*((3*x*x+3*x-1)%MOD)%MOD;
35     y=y*ni%MOD;
36     return y;
37 }
38 inline void resolve(ll x){
39     for(register int i=1;i<=cnt;i++){
40         if(p[i]>x)break;
41         if(x/p[i]*p[i]==x){
42             num[++tot]=p[i];
43             while(x/p[i]*p[i]==x)x/=p[i];
44         }
45     }
46     if(x>1)num[++tot]=x;
47 }
48 int main(){
49     memset(pri,1,sizeof(pri));
50     ini();
51     scanf("%lld",&T);
52     while(T--){
53         memset(num,0,sizeof(num));
54         tot=ans=0;
55         scanf("%lld",&n);
56         ans=calc(n);
57         resolve(n);
58         for(register ll i=1;i<(1<<tot);i++){
59             ll tmp=1,cnt1=0;
60             for(register ll j=0;j<tot;j++){
61                 if(i&(1<<j)){
62                     cnt1++;
63                     tmp=tmp*num[j+1]%MOD;
64                 }
65             }
66             //
67             if(cnt1&1){
68                 ans=(ans-(calc(n/tmp)*ksm(tmp,4))%MOD+MOD)%MOD;
69             }
70             else {
71                 ans=(ans+(calc(n/tmp)*ksm(tmp,4))%MOD+MOD)%MOD;
72             }
73         }
74         printf("%lld\n",(ans+MOD)%MOD);
75     }
76 }

聖誕快樂!!

『ZOJ 3547』The Boss on Mars (容斥原理)