【美团杯2020】平行四边形
分析:1 . 答案是(i,g^i%(n+1))后一项为原根的次方。采用反证法,假设有4个点:(a,g^a),(b,g^b),(c,g^c),(d,g^d);
2 . 若形成平行四边形则要满足:(1) a-b==c-d. (2)g^a-g^b==g^c-g^d ( 化简为 g^b ( g^(a-b) - 1 ) == g^d ( g^(c-d) -1) )
3 . 联立(1)(2)得必须a==c&&b==d才能形成平行四边形,而我们第一项的 i 避免了这一点,所以直接求n+1的原根
#include<bits/stdc++.h> #define lowbit(i) i&(-i) #define pb push_back using namespace std; typedef long long ll; ll ksm(ll a,ll b,ll mod){ ll t=1; while(b){ if(b&1) t=t*a%mod; b>>=1; a=a*a%mod; } return t; } ///求原根 ll solve(ll p,ll m){///p==phi(m) ll x=p; vector<ll>tmp; tmp.clear(); for(ll i=2;i*i<=x;i++){ if(x%i==0){ tmp.pb(i); while(x%i==0) x/=i; } } if(x>1) tmp.pb(x); for(ll i=2;;i++){ ll flag=1; for(auto x:tmp){ if(ksm(i,p/x,m)==1){ flag=0; break; } } if(flag) return i; } return -1; } int main(){ int t; scanf("%d",&t); while(t--){ ll n; scanf("%lld",&n); ll g=solve(n,n+1); if(g==-1){ printf("-1\n"); } else{ for(ll i=1;i<=n;i++) printf("%lld %lld\n",i,ksm(g,i,n+1)); } } return 0; }