题目链接:

http://codeforces.com/problemset/problem/595/B

题意:

有一个n位的电话号码,每位电话号码将分成n/k段,每段均为k个数,求出满足以下要求的电话号码个数

1)第i段可以整除a[i];

2)第i段不能以数字b[i]开头。

解题思路:

1、 第i段能被a[i]整除的的个数z=(10^k-1)/a[i]+1;

2、 能被a[i]整除但以b[i]开头的个数y有:设 MIN=b[i]*10^(k-1),MAX=(b[i]+1)*10^(k-1)-1;

    ①如果MIN/a[i]*a[i]=MIN, 则y=(MAX-MIN)/a[i]+1;

  ②如果①条件不满足,如果(MIN/a[i]+1)*a[i]<=MAX, 则y=(MAX-(MIN/a[i]+1)*a[i])/a[i]+1;

通过1和2可以得出第i段满足的号码个数为c[i]=z-y;将每一段满足情况的个数求出来,将它们乘起来就可以求出所要答案。

 

//借鉴了大神的思路

程序代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
#define LL long long
const int M=100000;
LL mod=1000000007;
LL a[M],b[M],num[M];
LL n,k,sum,m,cnt;

void init()
{
 for(LL i=1;i<=k;i++)
  cnt*=10;
  m=cnt/10;
  for(int i=0;i<n/k;i++)
  scanf("%d",&a[i]);
 for(LL i=0;i<n/k;i++)
  scanf("%d",&b[i]);
}

void work()
{
 for(LL i=0;i<n/k;i++)
  {
  num[i]=(cnt-1)/a[i]+1;
  LL MAX=(b[i]+1)*m-1;
  LL MIN=b[i]*m;
  LL temp=MIN/a[i];
  if(temp*a[i]==MIN)
   num[i]-=(MAX-MIN)/a[i]+1;
  else if((temp+1)*a[i]<=MAX)
    {
    MIN=(temp+1)*a[i];
    num[i]-=(MAX-MIN)/a[i]+1;
    }
  }
}
int main()
{
 sum=cnt=1;
 cin>>n>>k;
  init();
  work();

  for(LL i=0;i<n/k;i++)
   sum=((num[i]%mod)*sum)%mod;

  printf("%lld\n",sum%mod);
 return 0;
}
View Code