期望得分:100+55+0=155
实际得分:90+55+0=145
T1
入阵曲的削弱版,预处理前缀和,双指针确定行的上界和下界,然后维护个桶计算合法数量
挂了十分因为没处理好\(l=0\)
T2
注意到\(a_i\)的大小只有\(1e5\),考虑分别计算\(gcd\in(1,max_a)\)的个数
数组\(c[i]\)表示\(gcd\)为\(i\)或其倍数的方案数,数组\(c\)可以每行建个桶然后累乘求出
考虑如何将数组修改为\(gcd\)为\(i\)的方案数
多余的情况就是\(gcd\)为\(i\)的倍数,那么我们可以倒序求出每个\(c[i]\),然后计算\(c[i]\)时减去\(\sum_{j=2}^{\frac{max_a}{i}}c[i*j]\)
据说这种枚举复杂度是\(O(\ln x)\)的,咱也不会证
部分分就是子任务1爆搜,子任务2数据随机,就可以在搜到\(gcd=1\)时就不搜了,子任务6直接枚举\(C_n^i\)表示选i行,再乘上\(m^i*a\),貌似$ai< 1,2 $ 也挺好搞,但是我没去看
代码
T1
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+11;
int xl[35][N];
int qzhr[35][N];
int sum[N],num;
long long n,m,l,r;
long long ton[35*N];
long long qzh[35*N];
inline int read()
{
int s=0;
char ch=getchar();
while(ch>'9'||ch<'0')
ch=getchar();
while(ch>='0'&&ch<='9')
{
s=(s<<1)+(s<<3)+(ch^48);
ch=getchar();
}
return s;
}
inline int readm()
{
int s=0;
char ch=getchar();
while(ch>'9'||ch<'0')
ch=getchar();
return ch-48;
}
signed main()
{
long long ans=0;
bool jd=1;
n=read();
m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
xl[i][j]=readm();
if(!xl[i][j])
jd=0;
}
l=read();
r=read();
if(jd)
{
for(long long i=1;i<=n;i++)
for(long long j=1;j<=m;j++)
if(i*j>=l&&i*j<=r)
ans+=(m-j+1)*(n-i+1);
cout<<ans<<endl;
return 0;
}
if(l==0&&r==n*m)
{
for(long long i=1;i<=n;i++)
for(long long j=1;j<=m;j++)
ans+=(m-j+1)*(n-i+1);
cout<<ans<<endl;
return 0;
}
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
qzhr[i][j]=qzhr[i-1][j]+xl[i][j];
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
int qz=0;
for(int k=1;k<=num;k++)
{
ton[sum[k]]=0;
sum[k]=0;
}
num=0;
for(int k=1;k<=m;k++)
{
qz+=qzhr[j][k]-qzhr[i-1][k];
if(!ton[qz])
sum[++num]=qz;
ton[qz]++;
}
qzh[0]=ton[0];
for(int k=1;k<=qz;k++)
qzh[k]=qzh[k-1]+ton[k];
for(int k=1;k<=num;k++)
if(sum[k]>=l)
{
ans+=ton[sum[k]]*(qzh[sum[k]-l]-(sum[k]-r-1>=0?qzh[sum[k]-r-1]:0));
if(sum[k]>=l&&sum[k]<=r)
ans+=ton[sum[k]];
}
}
cout<<ans<<endl;
return 0;
}
T2
#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
const int N=100011;
int maxx;
int n,m,a[24][N];
long long ton[24][N];
long long tone[24][N];
long long c[N];
long long ans;
inline int read()
{
int s=0;
char ch=getchar();
while(ch>'9'||ch<'0')
ch=getchar();
while(ch>='0'&&ch<='9')
{
s=(s<<1)+(s<<3)+(ch^48);
ch=getchar();
}
return s;
}
signed main()
{
n=read();
m=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
a[i][j]=read();
maxx=max(maxx,a[i][j]);
tone[i][a[i][j]]++;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=maxx;j++)
for(int k=1;k*j<=maxx;k++)
ton[i][j]+=tone[i][k*j];
for(int j=1;j<=maxx;j++)
{
c[j]=1;
for(int i=1;i<=n;i++)
c[j]=(c[j]*(ton[i][j]+1)%mod);
c[j]=(c[j]+mod-1)%mod;
}
for(int i=maxx;i>=1;i--)
for(int j=2;j*i<=maxx;j++)
c[i]=(c[i]-c[i*j]+mod)%mod;
for(int i=1;i<=maxx;i++)
ans=(ans+c[i]*(long long)i%mod)%mod;
cout<<ans<<endl;
return 0;
}