bestcoder#51

bestcoder#51

A题:

求(n-1)!%n。

显然,若n不是素数,n的因子全都存在于1~n-1中,因此(n-1)!%n=0. (n=4时除外)

若n为素数,由威尔逊定理: (n,p互质-> (n-1)!=1(mod p)) ,(n-1)!%n=1。

打表也可以发现规律,注意n=4的时候答案为2的特判。

注意判素数时先筛出素数,在由筛出的素数去判断一个数是否为素数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<math.h>
#include<cctype>
#define ll long long
#define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
#define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
#define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
#define PII pair<int,int>
#define fst first
#define snd second
#define MP make_pair
#define PB push_back
#define RI(x) scanf("%d",&(x))
#define RII(x,y) scanf("%d%d",&(x),&(y))
#define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define DRI(x) int (x);scanf("%d",&(x))
#define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
#define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
#define RS(x) scanf("%s",x)
#define RSS(x,y) scanf("%s%s",x,y)
#define DRS(x) char x[maxn];scanf("%s",x)
#define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
#define MS0(a) memset((a),0,sizeof((a)))
#define MS1(a) memset((a),-1,sizeof((a)))
#define MS(a,b) memset((a),(b),sizeof((a)))
#define ALL(v) v.begin(),v.end()
#define SZ(v) (int)(v).size()

using namespace std;

const int maxn=1000100;
const int INF=(1<<29);
const double EPS=0.0000000001;
const double Pi=acos(-1.0);

ll n;

bool isprime[maxn];
vector<ll> prime;

void getP()
{
    MS(isprime,1);
    isprime[1]=0;
    REP(i,2,maxn-1){
        if(!isprime[i]) continue;
        REPP(j,i+i,maxn-1,i) isprime[j]=0;
    }
    REP(i,1,maxn-1){
        if(isprime[i]) prime.PB(i);
    }
}

bool isp(ll n)
{
    int sz=SZ(prime);
    for(ll i=0;i<sz&&prime[i]*prime[i]<=n;i++){
        if(n%prime[i]==0) return 0;
    }
    return 1;
}

int main()
{
   // freopen("in.txt","r",stdin);
    DRI(T);
   // Init();
    getP();
    while(T--){
        scanf("%I64d",&n);
        if(isp(n)) printf("%I64d\n",n-1);
        else if(n==4) puts("2");
        else puts("0");
    }
    return 0;
}
View Code

B题:

给出一个置换,求它的循环长度。

分解成循环求长度的最小公倍数。注意由于要取模,lcm不能用a*b/gcd(a,b)=a*b*inv(gcd(a,b))求,因为a和b已经被取模过,gcd(a,b)!=gcd(a%p,b%p)。

lcm的另一种求法:分解质因数。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<string>
#include<math.h>
#include<cctype>
#include<memory>
#define ll long long
#define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
#define MS0(a) memset((a),0,sizeof((a)))
#define SZ(v) (int)(v).size()
#pragma comment(linker, "/STACK:16777216")

using namespace std;

const int maxn=3000100;
const int INF=(1<<29);
const double EPS=0.0000000001;
const double Pi=acos(-1.0);

const ll MOD=3221225473;
int n;
int a[maxn];
bool vis[maxn];

#define MAXN 100010
bool isprime[MAXN];
int prime[MAXN],sz;
void getPrime()
{
    memset(isprime,1,sizeof(isprime));
    isprime[1]=0;
    REP(i,1,MAXN-1){
        if(!isprime[i]) continue;
        REPP(j,i+i,MAXN-1,i) isprime[j]=0;
    }
    sz=0;
    REP(i,2,MAXN-1){
        if(isprime[i]) prime[sz++]=i;
    }
}

ll qpow(ll n,ll k,ll p)
{
    ll res=1;
    while(k){
        if(k&1) res=(res*(n%p))%p;
        n=(n*n)%p;
        k>>=1;
    }
    return res;
}

ll lcm(ll a,ll b)
{
    ll res=1;
    a%=MOD,b%=MOD;
    REP(i,0,sz-1){
        int t=prime[i];
        if(a%t&&b%t) continue;
        if(t*t>a&&t*t>b) break;
        int cntA=0,cntB=0;
        while(a%t==0) a/=t,cntA++;
        while(b%t==0) b/=t,cntB++;
        ll cnt=max(cntA,cntB);
        res=(res*qpow(t,cnt,MOD))%MOD;
    }
    if(a!=1) res=(res*a)%MOD;
    if(b!=1) res=(res*b)%MOD;
    return res;
}

int main()
{
    freopen("in.txt","r",stdin);
    getPrime();
    int T;
    cin>>T;
    while(T--){
        scanf("%d",&n);
        REP(i,1,n) scanf("%d",&a[i]);
        ll ans=1;
        MS0(vis);
        REP(i,1,n){
            if(!vis[i]){
                vis[i]=1;
                ll tmp=1;
                for(int j=a[i];j!=i;j=a[j]){
                    tmp++;
                    vis[j]=1;
                }
                ans=lcm(ans,tmp)%MOD;
            }
        }
        printf("%lld\n",ans%MOD);
    }
    return 0;
}
View Code

 

posted @ 2015-08-16 12:07  __560  阅读(215)  评论(0编辑  收藏  举报