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;
}
posted @ 2021-11-11 21:55  BFNewdawn  阅读(42)  评论(0编辑  收藏  举报