考虑到非常困难。再简单的计数题也要认真看一眼。
P8809 [蓝桥杯 2022 国 C] 近似 GCD
思路
考虑刻画充要条件去计数。发现一个子区间合法的充要条件是至多一个数不是 \(g\) 的倍数。
将不是 \(g\) 倍数的东西看作 1,否则看作 0,合法充要条件是区间和小于等于 1。
于是双指针类似贪心的去做即可。对于每一个位置当作左端点然后记其合法的最右边的位置。
code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
typedef unsigned long long ll;
int a[N],colcnt=0,f[N];
ll cnt[N];
int n,g;
bool bei[N];
int main()
{cin>>n>>g;for(int i=1;i<=n;i++){cin>>a[i];}int t=n+1;f[n+1]=n+1;for(int i=n;i>=1;i--){f[i]=t;if(a[i]%g!=0) t=i;}for(int i=1;i<=n;i++){if(!(a[i]%g)) f[i]=f[f[i]];}ll ans=0;for(int i=1;i<=n;i++) ans+=f[i]-i-1;cout<<ans<<endl;
}