good array(數論 隨機演算法)

2022-09-06 22:54:27 字數 3534 閱讀 2624

題意:給出n個數(1<=ai<=1012),可以對這組數進行兩種操作加一或減一。問最少要幾次操作可以使這組數得gcd>1。

解法:我們先假設我們已經知道了素因子是什麼,假設其為p

'>p

,所以有乙個很明顯的貪心策略,就是每乙個數隻會變成與它相鄰的兩個是p

'>p

的倍數的正整數,所以我們就可以得到乙個o(n

)'>o(n)

的貪心策略。先把2

'>

2和3'>

3跑一遍(因為這兩個最容易成為答案,

p'>p

'>o(n

)'>2

'>3

'>然後就是隨機了,隨機抽取序列中的乙個數,令其為x

'>

x,然後把x

'>

x分解質因數,對它的每乙個質因數都跑一遍,然後再這麼操作x−1

'>

x−1和x+1

'>x+1

,這樣的話演算法錯誤的概率是1/21

2'>,然後重新隨機。這樣隨機 20 次之後,程式錯誤的概率就是2−20

#include#include #include #include #include #include #include #include #include #include #include #include #include #include typedef long long ll ;

#define int ll

#define mod 1000000007

#define gcd __gcd

#define rep(i , j , n) for(int i = j ; i <= n ; i++)

#define red(i , n , j) for(int i = n ; i >= j ; i--)

#define me(x , y) memset(x , y , sizeof(x))

//ll lcm(ll a , ll b)

ll quickpow(ll a , ll b)return ans;}

//int euler1(int x)if(x>1)ans-=ans/x;return ans;}

//const int n = 1e7+9; int vis[n],prime[n],phi[n];int euler2(int n)for(int j=1;j#define fi first

#define se second

#define lson l,mid,root<<1

#define rson mid+1,r,root<<1|1

using namespace std;

const int n = 1e6+100;

const int maxn = 2e5+9;

int n ;

int a[maxn] , p[maxn], len;

void euler1(int x)}}

if(x > 1) p[++len] = x ;

}int work(int x)

continue;

}int fron = a[i] / x ;

int bac = (fron+1)*x;

fron *= x ;

ans += min(a[i]-fron , bac - a[i]);

if(ans >= n)

}return ans ;

}void solve()

int ans = n ;

int num = 0 ;

rep(i , 1 , n)

}ans = min(ans , num);

num = 0;

rep(i , 1 , n)else if(a[i] % 3)

}ans = min(ans , num);

while(1)

euler1(a[x]-1);

rep(i , 1 , len)

euler1(a[x]+1);

rep(i , 1 , len)

end = clock();

if((end - begin)*1.0/clocks_per_sec > 2.0)

}cout << ans << endl;

}signed main()

}

cf官方題解:

#include#include #include #include #include #include #include #include #include #include #include #include #include #include typedef long long ll ;

#define int ll

#define mod 1000000007

#define gcd __gcd

#define rep(i , j , n) for(int i = j ; i <= n ; i++)

#define red(i , n , j) for(int i = n ; i >= j ; i--)

#define me(x , y) memset(x , y , sizeof(x))

//ll lcm(ll a , ll b)

ll quickpow(ll a , ll b)return ans;}

//int euler1(int x)if(x>1)ans-=ans/x;return ans;}

//const int n = 1e7+9; int vis[n],prime[n],phi[n];int euler2(int n)for(int j=1;j#define fi first

#define se second

#define lson l,mid,root<<1

#define rson mid+1,r,root<<1|1

using namespace std;

const int n = 1e6+100;

const int mx = 1e6+2 ;

const int maxn = 2e5+9;

int n , ans = maxn;

int a[maxn] , p[maxn], len;

bool chk[mx];

setcan;

vectorpr;

mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());//隨機數

void init()}}

}void add_prime(int u)}}

if(u > 1)

}int work(int u)

return ret ;

}void solve()

shuffle(per.begin() , per.end() , mt);

for(int i = 0 ; i < 100 && i < (int)per.size() ; i++)

}for(int v : can)

cout << ans << endl;

}signed main()

}

數論 Miller Rabin演算法

在我們需要判斷乙個數是否是素數的時候,最容易想到的就是那個熟悉的o n 的演算法。那個演算法非常的簡單易懂,但如果我們仔細想想,當n這個數字很大的時候,這個演算法其實是不夠用的,時間複雜度會相對比較高。怎麼解決呢?我們先來了解一下 費馬小定理 假設我們有乙個素數p,且另乙個數a和p互素,就可以得到a...

快速冪 數論演算法

題型 hdoj 1061 rightmost digit atcoder regular contest 113 b a b c 快速冪模板 int qmi int a,int k,int q return res hdoj 1061 rightmost digit include using na...

數論演算法 等模

在雜湊函式中,有很多地方是根據模運算來進行雜湊,所以某兩個整數都modn的值一樣,這兩個整數就可以看成是乙個等價類的 比如某個簡單的hash演算法是槽值為模7的餘數,那麼模7餘數相等的數就都是乙個等價類的,都會被hash到同乙個槽中 還比如 a,b z,當且僅當a和b除以2的餘數相同.這樣所有的偶數...