CF595B Pasha and Phone 题解
容斥 + 数学
能被 \(a_i\) 整除且开头不为 \(b_i\) 的个数 = 能被 \(a_i\) 整除的个数 - 能被 \(a_i\) 整除且开头为 \(b_i\) 的个数。
小于 \(x\) 且被 \(y\) 整除的正整数个数为 \(⌊\dfrac{x-1}y⌋+1\)。
设 \(mid1=⌊\dfrac{10^k-1}{a_i} ⌋+1\) 表示能被 \(a_i\) 整除的 \(k\) 位电话号码。
加上开头为 \(b_i\) 这一条件后,我们可以:能被 \(a_i\) 整除且开头不大于 \(b_i\) 的个数 - 能被 \(a_i\) 整除且开头小于 \(b_i\) 个数 = 能被 \(a_i\) 整除且开头为 \(b_i\) 的个数。
设 \(mid2=⌊\dfrac{10^{k-1}×b_i-1}{a_i} ⌋+1\),\(mid3=⌊\dfrac{10^{k-1}×(b_i+1)-1}{a_i} ⌋+1\),分别对应能被 \(a_i\) 整除且开头不大于 \(b_i\) 的个数 - 能被 \(a_i\) 整除且开头 小于 \(b_i\) 个数。
最后得到对应式 \(ans×(mid1-(mid3-mid2))\)。
注意到 \(b_i=0\) 时 \(mid3<0\),因此需要特判,直接 \(ans×(mid1-mid3)\)。
View code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ri register int
#define il inline
const int INF=0x3f3f3f3f,N=1e5+10,MOD=1e9+7;
int n,k,len=1,ans=1;
int a[N],b[N];
namespace RW{
il ll read(){
ll x=0,y=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
y=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*y;
}
using namespace RW;
signed main(){
n=read(),k=read();
for(ri i=1;i<=n/k;i++)
a[i]=read();
for(ri i=1;i<=n/k;i++)
b[i]=read();
for(ri i=1;i<=k;i++)
len*=10;
for(ri i=1;i<=n/k;i++){
int mid1=(len-1)/a[i]+1;
int mid2=(len/10*b[i]-1)/a[i]+1;
int mid3=(len/10*(b[i]+1)-1)/a[i]+1;
if(!b[i])
ans=ans*(mid1-mid3)%MOD;
else
ans=ans*(mid1-mid3+mid2)%MOD;
}
printf("%lld",ans);
return 0;
}