仪仗队(容斥,欧拉,打表)
Description
作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。 现在,C君希望你告诉他队伍整齐时能看到的学生人数。
Input
共一个数N。
Output
共一个数,即C君应看到的学生人数。
Sample Input
4
Sample Output
9
Hint
【数据规模和约定】 对于 100% 的数据,1 ≤ N ≤ 40000
题解:典型的容斥题,但是看了网上的有人推出用欧拉也能做,还有用莫比乌斯函数做的。。。脑洞大开;莫比乌斯看不懂,欧拉容斥做了一遍,算是复习一下吧;由于是N*N所以可以用欧拉,最后是answer*2+1,这个他们说是看出来的。。。。。还是容斥可靠;
容斥:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<vector> 7 using namespace std; 8 typedef long long LL; 9 vector<int>p; 10 void getp(int x){ 11 p.clear(); 12 for(int i=2;i*i<=x;i++){ 13 if(x%i==0){ 14 p.push_back(i); 15 while(x%i==0){ 16 x/=i; 17 } 18 } 19 } 20 if(x>1)p.push_back(x); 21 } 22 int getn(int x,LL n){ 23 LL sum=0; 24 getp(x); 25 for(int i=1;i<(1<<p.size());i++){ 26 LL temp=1,cnt=0; 27 for(int j=0;j<p.size();j++){ 28 if(i&(1<<j)){ 29 temp*=p[j];cnt++; 30 // printf("%d*",p[j]); 31 } 32 } 33 // printf("\n"); 34 if(cnt&1)sum+=n/temp; 35 else sum-=n/temp; 36 } 37 return n-sum; 38 } 39 int main(){ 40 LL N; 41 while(~scanf("%lld",&N)){ 42 N--; 43 LL ans=0; 44 // getn(48,100) 45 for(int i=1;i<=N;i++){ 46 ans+=getn(i,N); 47 // printf("%lld\n",getn(i,N)); 48 } 49 printf("%lld\n",ans+2); 50 } 51 return 0; 52 }
ouler:
LL ouler(LL n){ LL p=n; for(int i=2;i*i<=n;i++){ if(n%i==0){ p=p*(i-1)/i; while(n%i==0)n/=i; } } if(n>1)p=p*(n-1)/n; // printf("%lld\n",p); return p; } int main(){ LL N; while(~scanf("%lld",&N)){ LL ans=0; for(int i=1;i<N;i++){ ans+=ouler(i); } printf("%lld\n",ans*2+1); } return 0; }
欧拉打表:
const int MAXN=500005; LL dp[MAXN]; void db(){ dp[1]=1; for(int i=2;i<MAXN;i++){ if(!dp[i]){ for(int j=i;j<MAXN;j+=i){ if(!dp[j])dp[j]=j; // dp[j]=dp[j]*(i-1)/i; } } dp[i]+=dp[i-1]; } } int main(){ db(); LL N; while(~scanf("%lld",&N)){ printf("%lld\n",2*dp[N-1]+1); } return 0; }