http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2605

A^X mod P

Time Limit: 5000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

It's easy for ACMer to calculate A^X mod P. Now given seven integers n, A, K, a, b, m, P, and a function f(x) which defined as following.

f(x) = K, x = 1

f(x) = (a*f(x-1) + b)%m , x > 1

Now, Your task is to calculate

( A^(f(1)) + A^(f(2)) + A^(f(3)) + ...... + A^(f(n)) ) modular P.

输入

 In the first line there is an integer T (1 < T <= 40), which indicates the number of test cases, and then T test cases follow. A test case contains seven integers n, A, K, a, b, m, P in one line.

1 <= n <= 10^6

0 <= A, K, a, b <= 10^9

1 <= m, P <= 10^9

输出

 For each case, the output format is “Case #c: ans”.

c is the case number start from 1.

ans is the answer of this problem.

示例输入

2
3 2 1 1 1 100 100
3 15 123 2 3 1000 107

示例输出

Case #1: 14
Case #2: 63

提示

 

来源

2013年山东省第四届ACM大学生程序设计竞赛
 
 
分析:
 

中等难度数论题。

先考虑 X = f(x)

可加可不加的欧拉定理优化 { 注意本题A,P并不一定互质,使用欧拉定理优化的时候注意细节。 A^(X + phi(P)) mod P = A^X mod P 在X>0时成立,注意X=0时和X为phi(P)的倍数时的特判 } 对于取模后的X,在P为质数时,数量级仍达到10^9,考虑到数据量n<=10^6且T=40,显然本题不可用O(logX)的快速幂求解,(希望确实做到了这点,如果有快速幂过的,如果能交流下优化的方法,感激不尽)。

考虑O(1)做法。 加欧拉定理优化可令ph = phi(P),也可以ph取10^9 + 1 我们可以找到一个最小的数 k 满足k*k>ph.

然后对于每一个X,令 X = i*k + j 其中i和j满足 0 <= i < k 且 0 <= j < k

则A^X = A^(i*k +j) = ( (A^k) ^ i ) * (A ^ j)。 A^k为定值,而i,j均<k,两部分%P的值都可以在O(k)时间内预处理出来 然后对于每个X进行O(1)求解。

接着考虑f(x),直接按照题意递推计算即可,需要注意的是x=1时,K没有对m取模,换言之,可能大于m

每组的复杂度为O(sqrt(P) + n)

 

官方代码:

 #include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int n;
ll A,K,a,b,m,P;
ll powmod(ll a,ll n,ll m){
ll y=;
while(n){
if(n&) y=y*a%m;
n>>=;
a=a*a%m;
}
return y;
}
ll solve(){
ll f=K,sum=,tmp;
for(int i=;i<n;i++){
sum=(sum + powmod(A,f,P))%P;
f=(a*f + b)%m;
}
return sum;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("data.in","r",stdin);freopen("out.txt","w",stdout);
#endif
int T,C=;
scanf("%d",&T);
while(T--)
{
scanf("%d%I64d%I64d%I64d%I64d%I64d%I64d",&n,&A,&K,&a,&b,&m,&P);
printf("Case #%d: %I64d\n",++C,solve());
}
return ;
}
 

最新文章

  1. Css学习笔记 (一)
  2. noip2014提高组day2二题题解-rLq
  3. 如何免费访问Google?
  4. ListView中使用type需要注意的东西
  5. Openflow的转发与传统的转发区别和优势
  6. Datatable转换成List实体对象列表 几个实例
  7. Script.NET Perl解释器代码已经在GitHub开源发布
  8. UML 类图的关系
  9. sql注入数据库修复方法
  10. 论如何把JS踩在脚下 —— JQuery基础及Ajax请求详解
  11. 【Python3之面向对象进阶】
  12. hdu 4117 -- GRE Words (AC自动机+线段树)
  13. Windows 10 远程连接出现函数错误 【这可能由于CredSSP加密Oracle修正】
  14. 数位DP HDU - 2089 不要62
  15. 《DSP using MATLAB》Problem 7.24
  16. css firefox火狐浏览器下的兼容性问题
  17. USB-IF协会公布最新PD3.0(PPS)协议认证芯片和产品名单
  18. jqgrid 编辑行、新增行、删除行、保存行
  19. jeecg中的一个上下文工具类获取request,session
  20. 如何用Curl 来post xml 数据

热门文章

  1. 直接用Qt写soap
  2. MinGW
  3. mac 终端乱码
  4. Hibernate学习笔记1
  5. 选择Nodejs的N个理由
  6. 关于android端的json传输
  7. 安装redis,执行make test时遇到You need tcl 8.5 or newer in order to run the Redis test
  8. asp.Net2.0中TextBox设置只读后后台获取不到值的解决方法
  9. [knowledge][basic][hardware] 内存的硬件结构(转)
  10. 【后台测试】Linux下小试jmeter