题目链接:
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; }