日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jzoj3509-倒霉的小C【gcd,欧拉函数】

發(fā)布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jzoj3509-倒霉的小C【gcd,欧拉函数】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題


大意

畫n條線,每次坐標變換為(x+n,y+(?1)(i+1)?i)(i=1~n)(x+n,y+(-1)^{(i+1)}*i) \ \ \ (i=1\sim n)(x+n,y+(?1)(i+1)?i)???(i=1n)。給出n,求線穿過的格點數。


解題思路

首先我們想穿過格點的問題,我們可以無視方向,然后每次就當從(0,0)(0,0)(0,0)(n,i)(n,i)(n,i)劃一條線。然后我們可以發(fā)現穿過的格點數(算上起點)就是gcd(n,i)gcd(n,i)gcd(n,i),因為每次都會穿過(n/j,i/j)(j=1~gcd(n,i))(n/j,i/j)\ \ \ (j=1\sim gcd(n,i))(n/j,i/j)???(j=1gcd(n,i))這些點。
然后我們可以知道答案就是
1+∑i=1ngcd(n,i)1+\sum_{i=1}^n gcd(n,i)1+i=1n?gcd(n,i)
但是暴力枚舉會超時,我們需要想別的方法
∑i=1ngcd(n,i)=d\sum_{i=1}^n gcd(n,i)=di=1n?gcd(n,i)=d
=>∑d=1nd?∑i=1n(gcd(i,n)==d)=>\sum_{d=1}^n d*\sum ^n_{i=1}(gcd(i,n)==d)=>d=1n?d?i=1n?(gcd(i,n)==d)
∑d=1nd?∑i=1ngcd(i/d,n/d)=1\sum_{d=1}^n d*\sum ^n_{i=1}gcd(i/d,n/d)=1d=1n?d?i=1n?gcd(i/d,n/d)=1
因為要求gcd(i/d,n/d)=1gcd(i/d,n/d)=1gcd(i/d,n/d)=1,所以i的個數就是φ(n/d)\varphi(n/d)φ(n/d)
所以答案就是
∑d=1nd×φ(n/d)\sum_{d=1}^n d\times \varphi(n/d)d=1n?d×φ(n/d)
由于要求n/dn/dn/d是整數,所以我們可以化為
1+∑d∣nd×φ(n/d)1+\sum_{d|n} d\times \varphi(n/d)1+dn?d×φ(n/d)
然后暴力枚舉約數和暴力求歐拉函數值時間復雜度為O(nlogn)O(\sqrt n\ \ log\ n)O(n???log?n)


代碼

#include<cstdio> #include<algorithm> #define ll long long using namespace std; ll n,ans=1; ll phi(ll n)//求歐拉函數 {ll ans=n;for (ll i=2;i*i<=n;i++)if (n%i==0){ans=ans/i*(i-1);while (n%i==0) n/=i;}if (n>1) ans=ans/n*(n-1);return ans; } int main() {//freopen("beats.in","r",stdin);//freopen("beats.out","w",stdout);scanf("%lld",&n);for (ll i=1;i*i<=n;i++){if (!(n%i)) {ans+=phi(n/i)*i;if (i*i!=n) ans+=n/i*phi(i);}//求約數}printf("%lld",ans);return 0; }

總結

以上是生活随笔為你收集整理的jzoj3509-倒霉的小C【gcd,欧拉函数】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。