请计算这个方程组有多少合法的整数解,答案比较大,对m取余后输出。
对于样例,有三组解{1, 1}, {3, 1}, {1, 3}。
Input
单组测试数据。 第一行包含四个整数 n, k, l, m (2 ≤ n ≤ 10^18, 0 ≤ k ≤ 10^18, 0 ≤ l ≤ 64, 1 ≤ m ≤ 10^9 + 7)。
Output
对于每一组数据输出答案占一行。
Input示例
2 1 2 10
Output示例
3
题解:orz我就不来献丑了。。
此题由于方程中仅含位操作,所以首先可以考虑将k以二进制的形式分开来看每一位。
假设当前考虑的是k的第i位,那么这一位将由且仅由n个ai的第i位决定,其中,n个数的总情况数为2^n。
若k的第i位为0,那么a1, a2...an中,在第i位上必然不存在相邻的1,设所有满足不存在相邻1的情况数为x;
那么满足使k的第i位为1的情况数就是2^n - x,我们设y = 2^n - x。
于是若k在二进制的0 ~ L位中,存在p个1和q个0,ans即为 y^p * x^q。
对于解x的值,当n = 1,x = 2;当n = 2,x = 3;当n更大的时候,可以考虑第n位的两种情况,若第n位为0那么前n-1位只要满足“不存在相邻1”即可;若第n位为1,那么第n-1位必须为0,而前n-2位满足“不存在相邻1”即可。
于是得到转移方程:dp[n] = dp[n - 1] + dp[n - 2],但是n比较大,无法O(n)递推,但是很庆幸这个转移方程就是Fibonacci数列,很容易想到使用矩阵快速幂进行加速求得某项的值,于是此题得解。
以上内容写的比较啰嗦...
但是友情提示一句,需要特判考虑无解的情况:)
代码:
#include <stdio.h>
__int64 n, k, tmp, l, m, myresult, tmp1, mycount, fn, mymaxsize;
#define mymaxsize1 9223372036854775807 //2^63-1
void MyMultiply(__int64 A[2][2], __int64 B[2][2], __int64 C[2][2])
{
int i, j;
__int64 result[2][2], tmp;
result[0][0] = result[0][1] = result[1][0] = result[1][1] = 0;
for (i = 0; i < 2; ++i)
{
for (k = 0; k < 2; ++k)
{
tmp = A[i][k];
for (j = 0; j < 2; ++j)
{
result[i][j] = (result[i][j] + (tmp * B[k][j]) % m) % m;
// result[i][j] = result[i][j] + (A[i][k] * B[k][j]);
}
}
}
for (i = 0; i < 2; ++i)
{
for (j = 0; j < 2; ++j)
{
C[i][j] = result[i][j];
}
}
}
void GetMyPowerMod(__int64 x, __int64 y, __int64 m, __int64 &result)
{
result = 1;
__int64 tmp1=x;
while (y)
{
if (y & 1) { result = (result * tmp1) % m; }
y >>= 1;
tmp1 = (tmp1 * tmp1) % m;
}
}
void Bit1Count(__int64 x, __int64 &result)
{
result = 0;
for (result = 0; x; ++result)
{
x &= (x - 1);
}
}
void GetFib(__int64 n, __int64 &result)
{
n += 2;
__int64 resultarray[2][2], C[2][2];
resultarray[0][0] = resultarray[1][1] = 1;
resultarray[0][1] = resultarray[1][0] = 0;
C[0][1] = C[1][1] = C[1][0] = 1; C[0][0] = 0;
while (n)
{
if (n & 1)
{
MyMultiply(resultarray, C, resultarray);
}
n >>= 1;
MyMultiply(C, C, C);
}
result = resultarray[0][1];
}
int main()
{
scanf("%lld%lld%lld%lld", &n, &k, &l, &m);
if (l < 63)
{
GetMyPowerMod(2, l, mymaxsize1, tmp1);
if (tmp1<=k)
{
printf("0");
return 0;
}
}
Bit1Count(k, mycount);
GetFib(n, fn);
GetMyPowerMod(2, n, m, tmp1);
GetMyPowerMod(tmp1 - fn, mycount, m, myresult);
GetMyPowerMod(fn, l - mycount, m, tmp);
myresult = (myresult * tmp) % m;
if (myresult<0)
{
myresult += m;
}
printf("%lld", myresult);
for (int i = 1; i <= 10; ++i)
{
scanf("%lld", &n);
}
return 0;
}