前言
上午刚看的繁佬的乘法逆元,下午的题正好考到了,还是卡了没写出来。总结模板+模板题,欧拉筛模板,乘法逆元模板,快速幂模板。做个cv工程师就可以ac了,可惜我不配,一直wawawa。
赛前不努力,赛时哇哇哇。
一 题目描述
题目链接: link.
二 解题思路
1.欧拉筛(求出来孪生素数个数m)
2.乘法逆元(最后用于求解分数m/n mod 1e9+7的值,因为是分数不能直接模)
乘法逆元公式已经给了。
3快速幂(用于求解上面Q的mod-2次方问题)。
???没了???这就没了?
好像是没了,但是还剩下一句话,n个选取二个都是孪生素数的概率怎么算?
这个不会有人不会吧,巧了我就不会。
三 题解代码
#include<bits/stdc++.h>
using namespace std;
const int maxx = 1e7+10;
int prime[maxx+10];//筛素数的数组
int a[maxx+10];//n个数中有几个孪生素数
bool vis[maxx+10];//标记数组,0是i对应是素数,1是非素。
const int mod=1e9+7;//要模的值
typedef long long ll;
void init() //欧拉筛+判断n中有几个孪生素数的打表。
{
vis[0]=vis[1]=1;
int k=0;
for(int i=2;i<=maxx;i++){
if(vis[i]==0)prime[++k]=i;
for(int j=1;i*prime[j]<=maxx;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
for (ll i = 0; i <= 10000000; ++i) {
a[i] = a[i - 1];
if (!vis[i] && !vis[i - 2]) {
++a[i];
}
}
}
ll ksm(ll a ,ll k) //快速幂
{
ll rec=1;
while(k)
{
if (k&1)
rec=((rec%mod)*(a%mod))%mod;
a=((a%mod)*(a%mod))%mod;
k>>=1;
}
return rec%mod;
}
int main()
{
ll n;
int t;
cin>>t;
init();
while(t--)
{
cin>>n;
//cout<<bj[n]<<" ";
cout<<(a[n])*ksm(n*(n-1)/2,mod-2)%mod<<endl;//我们从1∼N中不放回地抽取两个数,抽到的是孪生素数的概率.
}
return 0;
}
四 总结
作为数论选手的话个人觉得这些常用的模板得了然于心,虽然比赛可以带模板,但是还是熟练敲出来好,毕竟cv工程师不太好。
五 每日共勉
千磨万击还坚劲,任他东南西北风。