Accept: 17 Submit: 50
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
Given one non-negative integer A and one positive integer B, it’s very easy for us to calculate A Mod B. Here A Mod B means the remainder of the answer after A is divided by B. For example, 7 Mod 5 = 2, 12 Mod 3 = 0, 0 Mod 3 = 0.
In this problem, we use the following rules to express A.
(1) One non-empty string that only contains {0,1,2,3,4,5,6,7,8,9} is valid.
For example, 123, 000213, 99213. (Leading zeros is OK in this problem)
(2) If w is valid, then [w]x if valid. Here x is one integer that 0<x<10.
For example, [012]2=012012, [35]3[7]1=3535357.
(3) If w and v are valid, then wv is valid.
For example, w=[231]2 and v=1, then wv=[231]21 is valid (which is 2312311).
Now you are given A and B. Here A is express as the rules above and B is simply one integer, you are expected to output the A Mod B.
Input
The first line of the input contains an integer T(T≤10), indicating the number of test cases.
Then T cases, for any case, only two lines.
The first line is one non-empty and valid string that expresses A, the length of the string is no more than 1,000.
The second line is one integer B(0<B<2,000,000,000).
You may assume that the length of number A in decimal notation will less than 2^63.
Output
Sample Input
Sample Output
Source
“高教社杯”第三届福建省大学生程序设计竞赛
快速模取幂 数论计算中经常出现的一种运算就是求一个数的幂ab对另外一个数n个模的运算,即计算: ab mod n (a,b,n是正整数) 由于计算机只能表示有限位的整数,所以编程时模取幂的运算要注意值的大小范围,当ab的值超过整数范围时,mod运算便无法进行。 如何解决这个问题,我们引出一个能计算ab mod n的值的有用算法——反复平方法,首先我们必须明确: d=ab mod n=(…((((a mod n)*a)mod n)*a)mod n…*a)mod n {共b个a} 由此可以引出一个迭代式 d:=a; for i:=2 to b do d:=d mod n*a; d:=d mod n; 时间复杂度为O(b),当b很大时,效率很低。我们可以将b转换为二进制数<bk,bk-1,...,b1,b0>,然后从最低位b0开始,由右至左逐位扫描,每次迭代时,用到下面两个恒等式: a2c mod n =(ac)2 mod n bi=0 a2c+1 mod n =a*(ac)2 mod n bi=1 (0<=c<=b) 其中c为b的二进制数的后缀(bi-1...b0)对应的十进制数,当c成倍增加时,算法保持d=ac mod n不变,直至c=b。 程序实现可如下: long long result(long long a,long long b,long long m) |
/*
快速幂
int pow(int a ,int k)
{
int rec = 1;
while( k )
{
if (k & 1)
rec *= a;
a *= a;
k >>= 1;
}
return rec;
}
& 表示的是k这一位是否为一,K>>= 表示K的位置右移以为,while(K)是直到K移到最后一位的时候弹出.
举个例子,3^13;13=1*2^3+1*2^2+0*2^1+1*2^0;那么第一次K=13;这个时候K&1表示探查2^0的这一位是否为1;为1,则进行rec*=a; k>>=1表示将13右移一位,即13/2;可以在之前的13的上面直接表示出来.6=1*2^2+1*2^1+0*2^0;这个时候,k&1则为0了。因为2^0的系数是0;
快速幂取模
int ModPow(int a,int b,int n)
{
int rec=1;
while(b)
{
if (b & 1)
rec = (rec * a) % n;
a = (a * a) % n;
b >>= 1;
}
return rec % n;
}
模运算规则:
模运算与基本四则运算有些相似,但是除法例外。其规则如下:
(a + b) % p = (a % p + b % p) % p
(a – b) % p = (a % p – b % p) % p
(a * b) % p = (a % p * b % p) % p
ab % p = ((a % p)b) % p
结合率:
((a+b) % p + c) % p = (a + (b+c) % p) % p
((a*b) % p * c)% p = (a * (b*c) % p) % p
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 1010
char s[N];
long long m;
struct node{
long long v,k;//位数
};
long long qmod(long long a,long long k){//快速取模
long long v=1;
//while(--k)v=(v*10)%m;
while(k){
if(k&1)v=(v*a)%m;
a=(a*a)%m;
k>>=1;
}
return v%m;
}
node build(int l,int r){
node p={0},t;
int i,flag=0;
int x,y,k;
for(i=l;i<=r;i++){
if(s[i]=='['){if(flag==0)x=i+1;flag++;}
else if(s[i]==']'){
flag--;
if(flag==0){//找到最外的[]
y=i-1;i++;k=s[i]-'0';
t=build(x,y);//得到[]里的位数m,和取模后的v
//cout<< "【"<<k<<"】"<<x<<" "<<y<<endl;
long long h=qmod(10,t.k);
long long g=1,e=h;
//cout<<t.k<<" "<<h<<endl;
p.k+=k*t.k;//总位数加上
p.v=(p.v*qmod(h,k))%m;//p.v*(10^t.k)
//t.v=qmod(t.v,k);//t.v^k************
while(--k){
g+=e;
e=(e*h)%m;
if(g>=m)g%=m;
}
//cout<<t.v<<"-----"<<g<<endl;
t.v=(t.v*g)%m;
p.v=(p.v+t.v)%m;
//cout<<p.v<<"*****"<<p.k<<endl;
}
}
else if(flag==0){//数字
p.v=p.v*10+s[i]-'0';
if(p.v>=m)p.v%=m;
p.k++;//位数加1
}
}
return p;
}
int main(){
int T;
//m=7;printf("%lld\n",qmod(10,2));
scanf("%d",&T);
while(T--){
scanf("%s%lld",s,&m);
printf("%lld\n",build(0,strlen(s)-1).v);
}
return 0;
}