随笔—邀请赛前训—Codeforces Round #330 (Div. 2) B题

Posted Shawn_Ji

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了随笔—邀请赛前训—Codeforces Round #330 (Div. 2) B题相关的知识,希望对你有一定的参考价值。

题意:

这道英文题的题意稍稍有点复杂。

找长度为n的数字序列有多少种。这个序列可以分为n/k段,每段k个数字。k个数可以变成一个十进制的数Xi。要求对这每n/k个数,剔除Xi可被ai整除的情况,剔除X的第一个数(包括前导0)是bi的情况。问剩下的组合有多少种。

 

思路:

这题我是一波三折的。首先也没有考虑很多,看着可以暴力模拟过程,我就直接开始敲了,几个for循环敲出来,再把bug调一调和特殊情况考虑考虑,交了之后开始TLE,这时候意识到复杂度太大了,于是开始优化,做了(b[i])*(mmax/10)-1    ~     (b[i]+1)*(mmax/10)-1    的循环范围优化后,后面的案例又超时了,后来觉得应该不能暴力模拟了,注意到一定范围内可以被一个数整除的数的数目是可以通过公式算的,这才用公式直接计算省去了for循环,这才过了题。

 

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

#define  MAX(x,y) (((x)>(y)) ? (x) : (y))
#define  MIN(x,y) (((x) < (y)) ? (x) : (y))
#define ABS(x) ((x)>0?(x):-(x))

const int inf = 0x7fffffff;
const int N=100000+10;
const long long mod=1e9+7;

int a[N];
int b[N];

int main()
{
//    freopen("out.txt", "w", stdout);
    int n;
    int k;
    cin>>n>>k;
    int kk=k;
    long long mmax=1;

    while(kk--)
        mmax *= 10;
//    cout<<mmax;

    int num=n/k;
    for(int i=0; i<num; i++)
        scanf("%d",a+i);
    for(int i=0; i<num; i++)
        scanf("%d",b+i);

    long long  ans=1;

    for(int i=0; i<num; i++)
    {
        long long cnt=(mmax-1)/a[i]+1;
        if(b[i] == 0){
            cnt-=(mmax/10-1)/a[i]+1;

        }
        else{
            cnt=cnt-( ((b[i]+1)*(mmax/10)-1)/a[i]+1 ) + ( ((b[i])*(mmax/10)-1)/a[i]+1 );

        }
        ans=ans*cnt % mod;
    }
    cout<<ans<<endl;
    return 0;
}

 

以上是关于随笔—邀请赛前训—Codeforces Round #330 (Div. 2) B题的主要内容,如果未能解决你的问题,请参考以下文章

随笔—邀请赛前训— Codeforces Round #330 (Div. 2) Vitaly and Night

随笔—邀请赛前训—Codeforces Round #330 (Div. 2) B题

随笔—邀请赛前训—Wizards' Duel

随笔—邀请赛前训—Duff and Weight Lifting

随笔—邀请赛前练— Codeforces Round #329 (Div. 2) 2Char

随笔—邀请赛前练—CodeForces 588B