题目类型:素数,模拟
题目大意:一维数组, 给出了数组长度和元素与递增步长,求能找到多少对(i, k)满足ai……ai+k*e,以i为起点,e为步长的子序列并且元素总和为素数。
解题思路:1.先筛素数,用线性筛。
2.遍历数组,若本位是 素数,则分别向前后和向后检索1,总数+t1+t2, 再把两个方向增加的方案算上,即总数+t1*t2。
3.基于乘积为素数,必然要求有且只有一个元素为素数,其他的数必为1,才能满足条件。因此, 只在遇到素数时,检索 其前后出现过的1的个数,并进行组合。
AC代码:
#include <bits/stdc++.h>
#define rep(x, a, b) for(int x = a; x <= b; x++)
#define pre(x, a, b) for(int x = b; x >= a; x--)
#define ll long long
#define endl '
'
#define PII pair<int, int>
using namespace std;
const int N = 2e5+10, M = 1e6+10;
int a[N], prime[M], idx;
bool isp[M];
int n, e;
void initP()
{
isp[0] = true;
isp[1] = true;
for(int i = 2; i< M; i++)
{
if(!isp[i]) prime[idx++] = i;
for(int j = 0; j<idx && i*prime[j] <= M; j++)
{
isp[i*prime[j]] = true;
if(i % prime[j] == 0) break;
}
}
}
void solve()
{
cin>>n>>e;
for(int i = 1; i<= n; i++) cin>>a[i];
ll ans = 0;
for(int i = 1; i<= n; i++)
{
if(!isp[a[i]])
{
ll t1 = 0, t2 = 0;
for(int j = i+e; j<= n; j+= e)
{
if(a[j] == 1)t1++;
else break;
}
for(int j = i-e; j>=1; j-=e)
{
if(a[j] == 1) t2++;
else break;
}
ans += t1 + t2 + t1 * t2 ;//分别与往后t1 和往前t2单向组合,再t1*t2 双向组合
}
}
cout<<ans<<endl;
}
int main()
{
int t = 1;
bool is = true;
if(is) cin>>t;
//getchar();
initP();
while(t -- )
{
solve();
}
return 0;
}