sdut2605山东省赛第四届/( A^f(1)+A^f(2)+ ... + A^f(n) )% P/存储中间值/将大数打表并用两个数组组合表示


1)如果用快速幂求A^X,那么整道题的最坏时间复杂度为:O(n)=(40*(10^6)*log(n)=O(10^9),超时。仔细看这道题的特点,如果用快速幂计算单个A^X还好,但是当n足够大,我们需要计算n个A^X时,不如提前打表,将所有可能的A^X计算出来,存入数组,直接调用来得方便。而(A^X)最多有P个不同值,P最大为10^9,数组的最大长度不过264144个(一个数组占1M的栈空间,1个int占4个字节,那么1024*1024/4=264144),空间上不能全部存储,不如再取一个中间值,即把(A^X)这个值中的X分解成i*k+j,而k任取一个可以表示的值,这里用500000,则第一个数组里只要存储A^1,A^2.A^3...A^500000,第二个数组里存储(A^500000)^1,(A^500000)^2,(A^500000)^3...(A^500000)^50000即可。(第二个数组的上限如果是A^(A^500000)^500000,会超时,如果是(A^500000)^5000,会WA)那么计算A^X,只需调用第二个数组里第X/50000的数,和第一个数组里X%500000的数相乘,就是(A^(X/500000))*(A^(X%500000)),然后照常取模,相加再取模即可。

#include <iostream>
#include <stdio.h>
using namespace std;
long long int n,A,K,a,b,m,P;
long long int  ff[1000010];
long long int ffa[500010];
long long int ffb[500010];

//long long int fff[1000010];
/*如果打表很多数的话,用快速幂反而就不合适了
long long int ys(long long int x){
    if(x==0)
        return 1;
    long long int temp=ys(x/2);
    long long int ans=temp*temp%P;
    if(x%2==1){
        ans*=A%P;
        ans%=P;
    }
    return ans;
}
*/
int main()
{
    int T;cin>>T;
    for(int kase=1;kase<=T;kase++){

        cin>>n>>A>>K>>a>>b>>m>>P;
        a%=m;b%=m;

        ff[1]=K;
        //fff[1]=ys(ff[1]);
        for(int i=2;i<=n;i++){
            ff[i]=((a*(ff[i-1]))%m+b)%m;
            //fff[i]=ys(ff[i]);
        }
        ffa[0]=1;
        for(int i=1;i<=500000;i++){
            ffa[i]=A*ffa[i-1]%P;
        }
        ffb[0]=1;
        for(int i=1;i<=50000;i++){
            ffb[i]=ffa[500000]*ffb[i-1]%P;
        }
        /*
        if(A%P==0){
            long long sun=0;
            for(int i=1;i<=n;i++){
                if(ff[i]==0)
                    sun+=1;
            }
            printf("Case #%d: %d\n",kase,sun);
            continue;
        }
        */
        long long int sum=0;
        for(int i=1;i<=n;i++){
            sum+=ffb[ff[i]/500000]*ffa[ff[i]%500000]%P;
            sum%=P;
        }
        printf("Case #%d: %d\n",kase,sum);
    }
} 



/**************************************
	Problem id	: SDUT OJ 2605 
	User name	:  
	Result		: Accepted 
	Take Memory	: 12520K 
	Take Time	: 1900MS 
	Submit Time	: 2016-03-20 
**************************************/


2)

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.

示例输入

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

示例输出

Case #1: 14Case #2: 63

提示

 

来源

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值