G. FQ 的函数

华中师范大学 2016 年“计蒜客杯”第十四届程序设计竞赛

G. FQ 的函数

Description
FQ 是个喜欢数学的孩子。有一天,FQ 发明了一个函数 FQ(n,p)。FQ(n,p)的值描述了 n!最多可以被 p 的多少次幂整除,其中 p 为一个素数。
举例来说,对于 FQ(8,3),我们要考查 8! = 8×7×6×5×4×3×2×1 = 40320。很容易发现,它可以被 32 整除,但是不能被 33 整除。所以FQ(8,3) = 2, 表示 8!最多可以被 32 整除。
对 FQ(k,p)可以严格的定义: k!可被p^FQ(k,p) 整除,但是不能被p^(FQ(k,p)+1) 整除。
ZQ 对 FQ 的发现很感兴趣,但是他对 FQ 在这个函数的讨论中仅使用十进制表示不满。ZQ于是定义了ZQ(n,p)。其中n是个p进制正整数,并且 ZQ(n,p)=FQ(n10,p)。其中n10表示 n 转换成十进制之后对应的数字。
本题的任务就是求出 ZQ(n,p)的值。注意:请将答案表示为十进制数。

Input
输入一个 T (T ≤ 50)表示 T 组数据。
每组测试数据占一行,是用空格分开的两个正两个整数 n,p。
数据保证:
(1) p≤16,并且 p 是素数。
(2) n 是一个 p 进制正整数,长度不超过10^5。
(3) 在高于十进制的进制中,使用 A 表示 10,B 表示 11,C 表示 12,D表示 13,E 表示 14,F 表示 15。

Output
对于每组测试用例,输出一行,包含一个整数表示你的答案。请将答案表示为十进制数。另外,由于答案可能太大,你只需要输出答案模1000000007 的余数。

Sample Input
2
11 2
1A1 11

Sample Output
1
22

Hint
样例第一组 (11)2 = (3)10,而 3!=6,可以被 2^1 整除,但不能被 2^2 整除。
样例第二组 (1A1)11 = (232)10,232! 可以被 11^22 整除,但是不能被 11^23 整除。

分析:
求n!中有多少个q就是将n反复除q直到比q小,注意到n是q进制的,所以除q就是将n右移一位,所以想到的就是每右移一次,就将结果加上n的十进制,但是右移n位复杂度O(n),将n转化成十进制也是O(n),因此O(n^2)肯定会超时。
其实O(n)的复杂度就可以求出答案,比如当n=3456,q=7时
sum=
3+
3*q+4+
(3*q+4) *q+
(3*q+4) *q+5) *q

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<deque>
#include<stack>
using namespace std;
#define LL long long
#define MOD 1000000007

char s[100000+10];
int q;
int len;

LL work(){
    LL sum=0;
    LL tmp=0;

    for(int i=0;i<len-1;i++){
        int num=s[i]>='A'?s[i]-'A'+10:s[i]-'0';
        tmp=(tmp*q%MOD+num)%MOD;
        sum=(sum+tmp)%MOD;
    }
    return sum;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%s %d",s,&q);
        len=strlen(s);
        printf("%lld\n",work());
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值