题面:https://files.cnblogs.com/files/ErkkiErkko/statement3.pdf
T1 a:三指针法?
分析:
枚举行的组合,三个指针分别表示左边界,右边界的min,右边界的max,扫一遍即可。
附上自己的90pts代码(没加特判)。
代码:
由于某些原因,代码丢失。
T2 b:容斥原理
分析:
枚举倍数,容斥一下。
附上SWHsz的巨神代码。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int mod=1e9+7,N=100005;
int f[25][N],t[N],mx,gcd[N],n,m,a[25][N],ans,tt[N];
inline int rd() {
static int x;x=0;static char ch;ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
return x;
}
int main() {
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d%d",&n,&m);
if(n==1) {
for(int i=1;i<=m;i++) ans=(ans+rd())%mod;
cout<<ans<<endl;
return 0;
}
for(int i=1;i<=n;i++) {
memset(t,0,sizeof t);
for(int j=1;j<=m;j++) {
a[i][j]=rd();
t[a[i][j]]++;
tt[a[i][j]]++;
mx=max(mx,a[i][j]);
}
for(int j=1;j<=mx;j++)
for(int k=1;j*k<=mx;k++)
f[i][j]+=t[j*k];
}
for(int G=mx;G;G--) {
gcd[G]=1;
for(int i=1;i<=n;i++)
gcd[G]=(1ll*gcd[G]*(f[i][G]+1))%mod;
gcd[G]=(gcd[G]-1+mod)%mod;
for(int i=2;i*G<=mx;i++)
gcd[G]=(gcd[G]-gcd[i*G]+mod)%mod;
ans=(ans+1ll*gcd[G]*G%mod)%mod;
}
cout<<ans<<endl;
}