AUG13-The Number Of Solutions

2 篇文章 0 订阅

Little Chief loves math. Most of all, he loves equations. He can solve any equation in the whole world. Recently he found one interesting and easy equation

x1d+x2d+x3d ≡ m (mod N)
Where x1, x2 and x3 are non negative integer numbers.

But, as always, this was easy enough for him and he solved it in just a few seconds. Now he wants you to do the same. Of course he understands that nobody is as good as he is, so he wants only the number of solutions of such equation which satisfies0 ≤ x1, x2, x3 ≤ upper for given upper, d,m andN. As the answer might be very large, he asks you to find the answer modulo1000000007.

Input

The first line of the input contains an integer T denoting the number of test cases. The description ofT test cases follow. Each test case consists of 4 integers:upper,d,m, N.

Output

For each test case, output a single line containing number of solutions for the corresponding equation, modulo1000000007. You may assume that00 is equal to 1.

Constraints

  • 1 ≤ T ≤ 10
  • 1 ≤ upper ≤ 1,000,000,000
  • 0 ≤ d ≤ 1,000,000,000
  • 1 ≤ N ≤ 40
  • 0 ≤ m < N

Example

Input:
2
2 2 3 5
1 2013 3 31

Output:
4
1

Explanation

The first equation has 4 solutions:

  • (0,2,2)
  • (2,2,0)
  • (2,0,2)
  • (1,1,1)

The second has only one:

  • (1,1,1)

如题可得余数是以N为循环的,所以根据加法乘法原理就可以求出

再用快速幂可以减少时间复杂度

#include <iostream>
#include <cstdio>
#define MAX 1000000007
#define LL unsigned long long int
using namespace std;
LL modpow(LL number,LL p,LL MOD)
{
if(p == 0)
return 1;
if(p%2 == 1)
return (number*modpow((number*number)%MOD , p>>1 ,MOD)) % MOD;
else
return modpow((number*number)%MOD, p>>1,MOD) % MOD;
}
 
int main()
{
int t;
LL sum;
LL uper,d,m,N;
LL x1,x2,x3;
scanf("%d",&t);
while(t--)
{
sum = 0;
scanf("%lld%lld%lld%lld",&uper,&d,&m,&N);
for(x1 = 0 ; x1 < N && x1 <= uper ; x1++)
{
for(x2 = 0 ; x2 < N && x2 <= uper; x2++)
{
for(x3 = 0 ; x3 < N && x3 <= uper; x3++)
{
LL a,b,c;
a = modpow(x1,d,N);
b = modpow(x2,d,N);
c = modpow(x3,d,N);
 
LL xx = (a + b + c)%N;
if(xx == m)
{
LL k1 = ((uper - x1)/N + 1)%MAX;
LL k2 = ((uper - x2)/N + 1)%MAX;
LL k3 = ((uper - x3)/N + 1)%MAX;
LL s = (((k1 * k2)%MAX)*k3)%MAX;
sum = (s + sum)%MAX;
}
}
}
}
 
printf("%lld\n",sum);
}
return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值