Codeforces gym 10025K: 2011-2012 Petrozavodsk Summer Training Camp, Kyiv + Kharkov NU Contest

Problem

Little Petya likes to draw on the walls a lot. He spent a lot of time, writing down all the integers from 1 to 10k , inclusive, in a row. After he had finished, he decided to show this masterpiece to his friend Masha. The only thing she wondered was the number of zeroes written on the wall. Help Petya to answer her question. Since this number can be very large, output it modulo p , otherwise the children will be scared.

Limits

TimeLimit(ms):2000

MemoryLimit(MB):256

k[1,1018]

p[1,109]

Look up Original Problem From here

Solution

窝们考虑 [1,10),[10,100),[100,1000) 这样的区间里零的个数, [1,10) 里有0个, [10,100) 里有9个, [100,1000) 里有180个, [103,104) 里有2700个, [104,105) 里有36000个 (写个小程序打表即知)

发现上述数字满足通项公式 an=9(n1)×10n2

那么, ans=(ki=19(i1)×10i2)+k (由于开区间,所以需要额外加上一个 k )。

用错位相减法求 Sk=ki=1(i1)×10i2

Sk=(11)×101+(21)×100++(k2)×10k3+(k1)×10k2

10Sk=(11)×100++(k3)×10k3+(k2)×10k2+(k1)×10k1

Sk10Sk=9Sk=100+101++10k2(k1)×10k1=1×(110k1)110(k1)×10k1

9Sk=(k1)×10k110k119

于是乎 ans=(k1)×10k110k119+k

第一项用快速幂可求,第二项有除法,无法取模运算,但发现第二项实际是形如 111... 的数,只含有1,用快速幂可求出。

Complexity

TimeComplexity:O(log2k)

MemoryComplexity:O(1)

My Code

//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi 3.1415926535898
#define eps 1e-9
#define MOD 1000000007
#define MAXN 2015
#define N
#define M
ll k,p,ans;
inline ll quick_power(ll x,ll y){
    if(y==0) return 1LL;
    ll res=quick_power(x,y>>1);
    if(y%2==0) return res*res%p;
    else return res*res%p*x%p;
}
ll oneoneone(ll n){
    if(n==0) return 0;
    if(n==1) return 1LL;
    ll n1=n>>1;
    ll right=oneoneone(n1);
    ll left=right;
    if(n%2LL==1LL) left=(left*10LL+1LL)%p;
    left=left*quick_power(10LL,n1)%p;
    return (left+right)%p;
}
int main(){
    freopen("zeroes.in","r",stdin);
    freopen("zeroes.out","w",stdout);
    cin>>k>>p;
    ans=(((k-1)%p)*quick_power(10LL,k-1)%p+(k%p))%p;
    ans=ans-oneoneone(k-1);
    ans=(ans%p+p)%p;
    cout<<ans<<endl;
}

你可能感兴趣的:(数学,快速幂)