P2158 [SDOI2008] 仪仗队

P2158 [SDOI2008] 仪仗队

这道题是一道欧拉函数的例题,但由于欧拉函数覆盖的数学前置知识有亿点多。

所以建议自行看前置知识:欧几里得+扩展欧几里得中国剩余定理积性函数(只用记住定义就行)

当然你也可以看一看 oi-wiki 上的欧拉函数但我们这里还是会讲的。

欧拉函数

定义: φ ( n ) \varphi(n) φ(n) 表示 1 ∼ n 1\sim n 1n 中与 n n n 互质的数即 1 ≤ t ≤ n , gcd ⁡ ( n , t ) = 1 1\le t\le n,\gcd(n,t)=1 1tn,gcd(n,t)=1 欧拉函数是一个积性函数即 n , m ∈ N + , n ⊥ m , φ ( n ) φ ( m ) = φ ( n m ) n,m\in \N^+,n\bot m,\varphi(n)\varphi(m)=\varphi(nm) n,mN+,nm,φ(n)φ(m)=φ(nm)

证明:我们先设 x 1 , x 2 , . . . , x φ ( n ) x_1,x_2,...,x_{\varphi(n)} x1,x2,...,xφ(n) 是与 n n n 互质的数, y 1 , y 2 , . . . , y φ ( m ) y_1,y_2,...,y_{\varphi(m)} y1,y2,...,yφ(m) 是与 m m m 互质的数, z 1 , z 2 , . . . , z φ ( n m ) z_1,z_2,...,z_{\varphi(nm)} z1,z2,...,zφ(nm) 是与 n m nm nm 互质的数。

根据中国剩余定理,由于 n ⊥ m n\bot m nm,存在唯一的 1 ≤ z ≤ n m 1\le z\le nm 1znm 满足 { z ≡ x i ( m o d n ) z ≡ y j ( m o d m ) \begin{cases}z\equiv x_i\pmod n\\z\equiv y_j\pmod m\end{cases} {zxi(modn)zyj(modm) 并且由于 x i ⊥ n , y j ⊥ m x_i\bot n,y_j \bot m xin,yjm 所以 z ⊥ n , z ⊥ m z\bot n,z\bot m zn,zm 也就是说 z ⊥ n m z\bot nm znm 那么对于某一组 ( x i , y j ) (x_i,y_j) (xi,yj) 肯定有一个(根据中国剩余定理)唯一的解 z k z_k zk 与它们相对且每组 ( x i , y j ) (x_i,y_j) (xi,yj) 是互不相同的。

证毕。

变式:

我们易知 p p p 是质数 φ ( p k ) = p k − p k − 1 = p k ( 1 − 1 p ) \varphi(p^k)=p^k-p^{k-1}=p^k(1-\frac{1}{p}) φ(pk)=pkpk1=pk(1p1)

n = p 1 k 1 p 2 k 2 . . . p d k d , φ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) . . . ( 1 − 1 p d ) n=p_1^{k_1}p_2^{k_2}...p_d^{k_d},\varphi(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_d}) n=p1k1p2k2...pdkd,φ(n)=n(1p11)(1p21)...(1pd1)

做题思路

做这道题时,我也是看了题解,发现大佬们都说只要 x ⊥ y x\bot y xy 就能被看见,左下角是 ( 0 , 0 ) (0,0) (0,0),当然还有几个特殊情况,后面慢慢说
在这里插入图片描述
画红圈的地方都是特殊情况,特殊情况先不考虑,先考虑不是特殊情况

在这里插入图片描述
我们先考虑点 ( 9 , 3 ) (9,3) (9,3) 它的 gcd ⁡ ( x , y ) = 3 \gcd(x,y)=3 gcd(x,y)=3 那么我们就分成三段,第一段是点 ( 9 , 3 ) (9,3) (9,3) 到点 ( 6 , 2 ) (6,2) (6,2),第二段是点 ( 6 , 2 ) (6,2) (6,2) 到点 ( 3 , 1 ) (3,1) (3,1),第三段是点 ( 3 , 1 ) (3,1) (3,1) 到点 ( 0 , 0 ) (0,0) (0,0) 我们可以发现,这三段是一毛一样的,而且都是由第三段复制平移的,因此,它们的角度是不变的,所以,我们可以将此题改成:点 ( x , y ) (x,y) (x,y) ( x − gcd ⁡ ( x , y ) , y − gcd ⁡ ( x , y ) ) (x-\gcd(x,y),y-\gcd(x,y)) (xgcd(x,y),ygcd(x,y)) 挡住了,因此,只要 ( x , y ) (x,y) (x,y) gcd ⁡ ( x , y ) = 1 \gcd(x,y)=1 gcd(x,y)=1 x ⊥ y x\bot y xy 就行。

现在我们就要考虑,怎样才能求出。

我们只需要分成两部分,因为我们发现他是对称的。

代码:

#include<bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define ll long long
#define ull unsigned long long
#define db double
#define x first
#define y second
#define fast ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
#define endl '\n'
#define pb push_back
#define swap(a,b) a=a^b,b=a^b,a=a^b
#define mem(x,a) memset(x,a,sizeof(x))
#define rep(l,r,i) for(int i=l,END##i=r;i<=END##i;i++)
#define per(r,l,i) for(int i=r,END##i=l;i>=END##i;i--)
#define sc scanf
#define pr printf
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
using namespace std;
const int N=40010;
int phi[N],p[N],cnt;
bitset<N>vis;
int main(){
    ll ans=0;
    int n;cin>>n;
    phi[1]=1;
    rep(2,n,i){
        if(!vis[i])p[++cnt]=i,phi[i]=i-1;
        for(int j=1;p[j]<=n/i;j++){
            vis[p[j]*i]=true;
            if(i%p[j]==0){
                phi[p[j]*i]=phi[i]*p[j];
                break;
            }
            phi[p[j]*i]=phi[i]*phi[p[j]];
        }
    }
    rep(1,n-1,i)
        ans+=phi[i];
    printf("%lld\n",n==1?0:ans*2+1);
    return 0;
}
  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值