Friend

Description

On an alien planet, every extraterrestrial is born with a number. If the sum of two numbers is a prime number, then two extraterrestrials can be friends. But every extraterrestrial can only has at most one friend. You are given all number of the extraterrestrials, please determining the maximum number of friend pair.

Input

There are several test cases.
Each test start with positive integers N(1 ≤ N ≤ 100), which means there are N extraterrestrials on the alien planet. 
The following N lines, each line contains a positive integer pi ( 2 ≤ pi ≤10^18),indicate the i-th extraterrestrial is born with pi number.
The input will finish with the end of file.

Output

For each the case, your program will output maximum number of friend pair.

Sample Input

3
2
2
3

4
2
5
3
8

Sample Output

1
2

思路:題目是朋友有多少對,是配對問題,聯想到二分圖,求最大匹配。條件是加起來是素數(質數),於是要求素數,數可能是10^18的,太大,直接求會超時,就要用到拉賓米勒數素數 來求,就是利用數論裏面的概率來求,隨機產生數。如果它(n)爲質素就滿足a^n-1%n==1(費馬小定理、數論) a爲隨機產生(2=<a<=n-2)  ,a^n-1%n==1直接去模可能會超時,就要用快速冪取模來寫,用快速冪取模的時候s=(s*a)%n;可能會超出long long,所以又要經行處理,優化。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<time.h>
using namespace std;
typedef unsigned long long LL;
LL sum[101];
int a[101][101];
int n,vis[101],cn[101];

LL multi(LL a,LL b,LL n)  //加法代替乘法,防止溢出 long long
{
   LL s=0;
    while(b)
    {
        if(b%2==1) s=(s+a)%n;
          b/=2; 
        a=(a+a)%n;
    }
    return s; 
}
LL mod(LL a,LL b,LL n)
{
    LL s=1;
    while(b)
    {
        if(b%2==1) s=multi(s,a,n);//<span style="color:#ff0000;">s=(s*a)%n;</span>
         b/=2;
        a=multi(a,a,n);
    }
    return s;
}

//拉賓米勒數素數 
bool test(LL n)
{
    LL a,x;
    int k=0,i,j;
    if(n<2)  return 0;
    if(n==2) return 1;//2是唯一的偶素數,直接返回
    if(n%2==0)  return 0;
    srand((LL)time(0));
    for(i=0;i<10;i++)  //測試最大次數
    {
       a=rand()%(n-2)+2;  //生成一個2到n-2的數字 
        x=mod(a,n-1,n); //快速冪(a^n-1)%n==1 費馬小定理(a爲整數,a,n互質)
        if(x!=1)//結果不是1,不是素數
            return 0;
    }
    return 1;//是素數
}
int funxx(int u)
{
 int i;
 for(i=1;i<=n;i++)
 {
   if(a[u][i]&&!vis[i])
   {
     vis[i]=1;
     if(cn[i]==-1||funxx(cn[i]))
      {
        cn[i]=u;
        return 1;                          
      }                    
   }                
 }   
 return 0;
}
int hun()
{
  int i,count=0;
   memset(cn,-1,sizeof(cn)); 
   for(i=1;i<=n;i++)
   {
    memset(vis,0,sizeof(vis));
    if(funxx(i))
    count++;                 
   }   
   return count;
}
int main()
{
int i,j;
while(scanf("%d",&n)==1)
{
   memset(a,0,sizeof(a));
   for(i=1;i<=n;i++)
     scanf("%lld",&sum[i]);  
   for(i=1;i<=n;i++)
    {
      for(j=i+1;j<=n;j++)
      {
        if(test(sum[i]+sum[j])) {a[i][j]=1;a[j][i]=1;}                                   
      }               
    }
   printf("%d\n",hun()/2);//二分圖 
}
return 0;
}



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