//来自kuangbin的ACM模板
//大整数约数和
/*
POJ 1845 Sumdiv
求A^B的所有约数之和%9901
*/
/*
大整数的约数和 三个问题
1.约数和结论-对于一个大整数N,他的因数分解式为 ( a1^x1 ) * ( a2 ^ x2) * (a3^x3 )... ,那么约数和 sum = ( 1 + a1 + a1^2 + ... a1^x1 ) * ( 1 + a2 + a2^2 + ... a2^x2 ) * ...
2.等比数列和的递归表达式:
1 + p + p^2 + p^3 +...+ p^n
= (n为奇数时,一共有偶数项)(1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))
= (n为偶数时,一共有奇数项)(1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2)
3.因数分解
*/
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define MOD 9901
//******************************************
//素数筛选和合数分解
const int MAXN=10000;
int prime[MAXN+1];
void getPrime()
{
memset(prime,0,sizeof(prime));
for(int i=2;i<=MAXN;i++)
{
if(!prime[i])prime[++prime[0]]=i;
for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++)
{
prime[prime[j]*i]=1;
if(i%prime[j]==0) break;
}
}
}
long long factor[100][2];
int fatCnt;
int getFactors(long long x)
{
fatCnt=0;
long long tmp=x;
for(int i=1;prime[i]<=tmp/prime[i];i++)
{
factor[fatCnt][1]=0;
if(tmp%prime[i]==0)
{
factor[fatCnt][0]=prime[i];
while(tmp%prime[i]==0)
{
factor[fatCnt][1]++;
tmp/=prime[i];
}
fatCnt++;
}
}
if(tmp!=1)
{
factor[fatCnt][0]=tmp;
factor[fatCnt++][1]=1;
}
return fatCnt;
}
//******************************************
long long pow_m(long long a,long long n)//快速模幂运算
{
long long res=1;
long long tmp=a%MOD;
while(n)
{
if(n&1){res*=tmp;res%=MOD;}
n>>=1;
tmp*=tmp;
tmp%=MOD;
}
return res;
}
//计算1+p+p^2+````+p^n , 计算等比数列的和对mod取模算法
//等比数列和的递归运算,复杂度O(logN * logN)
//还可以使用等比数列和公式求解,此处使用等比数列的递推公式求解
long long sum(long long p,long long n)
{
if(p==0)return 0;
if(n==0)return 1;
if(n&1)//奇数
{
return ((1+pow_m(p,n/2+1))%MOD*sum(p,n/2)%MOD)%MOD;
}
else return ((1+pow_m(p,n/2+1))%MOD*sum(p,n/2-1)+pow_m(p,n/2)%MOD)%MOD;
}
int main()
{
int A,B;
getPrime();
while(scanf("%d%d",&A,&B)!=EOF)
{
getFactors(A);
long long ans=1;
for(int i=0;i<fatCnt;i++)
{
ans*=(sum(factor[i][0],B*factor[i][1])%MOD);
ans%=MOD;
}
printf("%I64d\n",ans);
}
return 0;
}
//HDU6069
//大整数约数的个数
//大整数约数个数结论:对于大整数N的因数表达式 N = x1^a1 * x2^a2 ...xn^an
//他的约数的个数是sum = ( 1 + a1 ) *(1 + a2 ) ... ( 1 + an )
//本题还要注意因数分解的方法,认识到给定的数据范围的特殊性,就是对于1e6以外的数,他要么是质数,要么他是1e6以内的质数的幂积和1e6以外的一个质数的幂积,不可能是1e6以外的两个质数的幂积,因为那样一定超过1e12.同时因为L和R的间隔不大于1e6,可以考虑大区间求质数的方法进行因数分解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
using namespace std ;
const int maxn = 1e6 +10 ;
const int maxm = 1e6 ;
typedef long long ll ;
const ll mod = 998244353 ;
bool notprime[maxn] ;
ll prime[maxn] ;
void getprime(){
memset( notprime , false , sizeof( notprime )) ;
prime[0] = 0 ;
for( ll i = 2 ;i<=maxm ;i++){
if( !notprime[i] )
prime[ ++ prime[0] ] = i ;
for( ll j = 2 ; ( ll ) j* i <maxn ; j ++)
notprime[i * j ] = true ;
}
}
ll L , R , K , ans ;
ll dp[maxn] ;
ll sp[maxn] ;
void solve(){
ans = 0 ;
if( L == 1 ){
ans = 1 ;
L = 2 ;
}
for(ll i = 0 ; i< R-L + 1 ;i++){
dp[ i ] = i + L ;
}
memset( sp , -1 , sizeof( sp )) ;
for( ll i = 1 ;i<= prime[0] && prime[i] <= R ;i++){
ll s = L / prime[i] + ( L % prime[i] > 0 ) ;
if(s == 1) s = 2 ;
for( ll j = s ; ( ll ) j* prime[i] <= R; j++){
if( ( ll ) j *prime[i] >= L ){
ll temp = 0 ;
/* ll tp = ( ll ) j* prime[i] ; while( tp % prime[i] == 0 ){ temp ++ ; tp /= prime[i ] ; } */
ll pos = ( ll ) j * prime[i] - L ;
while( dp[pos] % prime[i] == 0 ){
temp ++ ;
dp[pos] /= prime[i] ;
}
if( sp[pos] == -1){
sp[pos] = ( temp* K + 1) % mod ;
}
else{
sp[pos] = ( sp[pos] * ( ( temp * K + 1) % mod ) ) % mod ;
}
// cout<<pos + L <<" "<<sp[pos]<<" ====="<<endl;
}
}
}
}
int main(){
getprime() ;
int a ;
scanf("%d" , & a) ;
while(a --){
scanf("%lld%lld%lld" , & L, & R , & K) ;
solve() ;
for(ll i = 0 ;i< R - L + 1; i++){
if( sp[i]== -1 )
ans = ( ans + K + 1 ) % mod ;
else {
if( dp[i] == 1)
ans = ( ans + sp[i] ) % mod ;
else
ans = ( ans + sp[i] * ( K + 1) % mod ) % mod ;
}
}
printf("%lld\n" , ans % mod);
}
return 0 ;
}