美团杯2020 - 平行四边形(原根)
題目鏈接:點擊查看
題目大意:
蒜斜非常喜歡下圍棋。自從AlphaOg面世以來,他就立志一定要研究出AlphaOg的破綻。 終于,他發(fā)現(xiàn)當AlphaOg遇到一種特殊局面后,它的神經(jīng)網(wǎng)絡會自動輸出“投降”!
隨著進一步的研究,蒜斜發(fā)現(xiàn)這種局面有著更一般的特性,不僅僅局限于固定大小棋盤。 具體來說,當棋盤大小是?nn(n+1n+1?是一個質(zhì)數(shù))且棋盤上恰好有?nn?個棋子的時候,如果這些棋子的位置滿足下列條件,那么 AlphaOg 就會直接投降。假設第?ii?個棋子的位置是點?PiPi,處在第?xixi?行第?yiyi?列,那么這些坐標需要滿足:
憑借這項發(fā)現(xiàn),蒜斜榮獲了“北大算協(xié)吉祥物”的稱號。 如果你也能找出一種合法方案,蒜斜的稱號就是你的了!
輸入格式
輸入第一行包含一個整數(shù)?t(1≤t≤10),表示數(shù)據(jù)組數(shù)。
對于每組數(shù)據(jù),輸入第一行包含一個整數(shù)?n(4≤n≤1000),保證?n+1 是一個質(zhì)數(shù)。
輸出格式
對于每組數(shù)據(jù),如果無解輸出一行一個整數(shù) -1。否則輸出?nn?行,每行兩個整數(shù)?(xi,yi)(1≤xi≤n,1≤yi≤n),表示第?ii?個棋子的坐標。如果坐標方案不唯一,你只需要輸出任意一種。
樣例一
input
1 4output
1 1 3 2 4 3 2 4限制與約定
Small Task:?n≤12n≤12。
Large Task:?n≤1000n≤1000。
時間限制:1s1s
空間限制:512MB
題目分析:首先需要知道原根的定義:
假設一個數(shù)g是P的原根,那么g^i mod P的結果兩兩不同,且有 1<g<P,0<i<P,歸根到底就是g^(P-1) = 1 (mod P)當且僅當指數(shù)為P-1的時候成立.(這里P是素數(shù))。(百度百科)
?換句話說,質(zhì)數(shù) P 一定有原根
既然題目提示了 n + 1 是一個質(zhì)數(shù),結合到原根上去,不難發(fā)現(xiàn) g ^ i % ( n + 1 ) 的集合符合 1 ~ n 的一個排列
這樣情況一和情況二都滿足了,只需要證明情況三也滿足就ok了
任取四個點 A( a , g^a ) ,?B( b , g^b ) ,?C( c , g^c ) ,?D( d , g^d ) ,如果四個點想要構成平行四邊形的話,那么需要同時滿足下面兩個條件,且共用的點至多有一個:假設 b < a 且 d < c
當 a - b == c - d 時,g^a - g^b = g^b * ( g^( a - b )?- 1 ) ,同理 g^c - g^d = g^d * ( g^( c - d ) - 1 ),因為 a - b == c - d ,所以?g^b * ( g^( a - b )?- 1 )? 與 g^d * ( g^( c - d ) - 1 ) 中的?g^( a - b ) ==?g^( c - d ) ,所以將括號約分之后可以得到 g^b == g^d,再帶回原式?g^a - g^b == g^c - g^d 中,可以得出 g^a == g^c,根據(jù)原根的定義可知,此時 b == d 且 a == c ,也就是點 A 與點?C 重合,且點 B 與點 D 重合,無法做到既是兩邊平行且相等,同時至多只有一個點共用,所以情況 3 成立
綜上,只需要讓 x 坐標為 i ,y 坐標為 g^i%P 即可,至于原根 g ,可以根據(jù)其定義暴力求解
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e3+100;bool vis[N];int find_root(int mod) {for(int i=2;i<mod;i++){memset(vis,false,sizeof(vis));bool flag=true;int x=i;for(int j=1;j<=mod-1;j++){if(vis[x]){flag=false;break;}vis[x]=true;x=x*i%mod;}if(flag)return i;} }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--){int n;scanf("%d",&n);int mod=n+1;int rt=find_root(n+1);int x=rt;for(int i=1;i<=n;i++){printf("%d %d\n",i,x);x=x*rt%mod;}}return 0; }?
總結
以上是生活随笔為你收集整理的美团杯2020 - 平行四边形(原根)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1355C C
- 下一篇: 美团杯2020 - 半前缀计数(后缀自动