題意:給出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的餘數相同.這樣所有的偶數...