NOI.AC 【CSP2019模擬Day 4】排列

題目描述

在這裏插入圖片描述

題解

該題極其符合人類思維邏輯,我們一般用兩個字來形容這種題“水題”。
在草稿紙上畫一下這個序列的樣子
k+1k+2k+3n123kk+1\quad k+2\quad k+3\quad\cdots\cdots \quad n \quad 1\quad 2 \quad3\quad\cdots\cdots k
我們把一個循環看成許多次跳躍,每次從第ii個位置跳到第a[i]a[i]個位置,規定方向向右。可以發現每一步的跳躍長度是相等的爲kk,每一個循環獨立,並且每一個循環的長度(稱其爲cntcnt)也是相等的(並且在形式上是相同的)。(因爲錯位後的位置關係是沒有改變的)
所以我們只需求出cntcnt,答案爲n/cntn/cnt
怎樣求cntcnt呢。對70%70\%的數據,我們可以暴力的模擬跳躍的過程,最壞情況是O(n)O(n)的。
對於全部數據(貌似更容易想到這個吧),可以想象跳躍的過程,每次跳kk這麼長,在一個長度爲nn的環上跳回原點,跳躍長度爲lcm(n,k)lcm(n,k),所以cntcnt等於跳躍步數爲lcm(n,k)/klcm(n,k)/kAns=n/(lcm(n,k)/k)Ans=n/(lcm(n,k)/k)
整理一下Ans=(nk)/lcm(n,k)=gcd(n,k)Ans=(n*k)/lcm(n,k)=gcd(n,k)

代碼

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=int(1e6+5);
#define int long long
int n,k;
int a[MAXN];
int gcd(int a,int b) {
    return (b==0)?a:gcd(b,a%b);
}
signed main()
{
    scanf("%lld%lld",&n,&k);
    /*
    for(int i=k+1;i<=n;i++)
        a[i-k]=i;
    for(int i=1;i<=k;i++)
        a[n-k+i]=i;
    int st=1,nw=1,cnt=0;
    do {
        cnt++;
        nw=a[nw];
    }while(st!=nw);
    printf("%d\n",n/cnt);
    */
    printf("%lld",gcd(n,k));
}

抱歉,之前被long longlong\ long搞了,就懶得改完了。


ThanksThanks ForFor Reading!Reading!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章