HDU 4990 Reading comprehension(递推+快速幂 或 矩阵快速幂)

来源:互联网 发布:mongodb 默认端口 编辑:程序博客网 时间:2024/05/19 22:03

Reading comprehension

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 930    Accepted Submission(s): 362


Problem Description
Read the program below carefully then answer the question.
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include<iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include<vector>

const int MAX=100000*2;
const int INF=1e9;

int main()
{
  int n,m,ans,i;
  while(scanf("%d%d",&n,&m)!=EOF)
  {
    ans=0;
    for(i=1;i<=n;i++)
    {
      if(i&1)ans=(ans*2+1)%m;
      else ans=ans*2%m;
    }
    printf("%d\n",ans);
  }
  return 0;
}
 

Input
Multi test cases,each line will contain two integers n and m. Process to end of file.
[Technical Specification]
1<=n, m <= 1000000000
 

Output
For each case,output an integer,represents the output of above program.
 

Sample Input
1 103 100
 

Sample Output
15
 

Source
BestCoder Round #8
 

题目大意:如题中程序所示,给出n和m,快速求出ans的值。

解题思路:

1、递推+快速幂

当i是偶数时,a[i]=2*a[i-1](i>=2);

当i是奇数时,a[i]=2*a[i-1]+1(i>=3,a[1]=1)。


对于偶数项,可以得到递推公式为:a[i]=2*a[i-1]=2*(2*a[i-2]+1)=4*a[i-2]+2(i为偶数,i>=4,a[2]=2)

如果令a[0]=0;则a[i]=4*a[i-2]+2(i为偶数,i>=2,a[0]=0)

a[2]=4*a[0]+2;

a[4]=4*a[2]+2=4^2*a[0]+8+2;

a[6]=4*a[4]+2=4^2*a[2]+8+2=4^3*a[0]+32+8+2;

a[8]=4*a[6]+2=4^2*a[4]+8+2=4^3*a[2]+32+8+2=4^4*a[0]+128+32+8+2;

……………………………………………………………………………………;

a[n]=4^(n/2)*a[0]+2+8+……+2*4^(n/2-1)=0+2+8+……+2*4^(n/2-1)=2*(1-4^(n/2))/(1-4)=(2^(n+1)-2)/3(n>=2n为偶数)

对于奇数项,利用递推公式a[i]=2*a[i-1]+1(i>=3,a[1]=1),因为i为奇数时,i-1一定是偶数。

a[n]=2*a[n-1]+1=2*(2^n-2)/3+1=(2^(n+1)-4)/3+1=(2^(n+1)-1)/3(n>=1,n为奇数);


对于(a / b) mod c(a / b) mod c = a mod (b*c) / b成立。

证明:设x ≡ a/b (mod c),根据同余式的性质两边同时乘以b,得b≡ a (mod b*c),

根据同余式的性质得a ≡ bx (mod b*c),所以x=a mod (b*c) / b。


综上所述:

当n为偶数时,a[n] = (2^(n+1) - 2)/3;当n为奇数时,a[n] = (2^(n+1) - 1)/3


快速幂求解即可。

代码如下:

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <iostream>#include <algorithm>#include <string>#include <vector>#include <deque>#include <list>#include <set>#include <map>#include <stack>#include <queue>#include <numeric>#include <iomanip>#include <bitset>#include <sstream>#include <fstream>#include <limits.h>#define debug "output for debug\n"#define pi (acos(-1.0))#define eps (1e-6)#define inf (1<<28)#define sqr(x) (x) * (x)#define mod 1000000007using namespace std;typedef long long ll;typedef unsigned long long ULL;ll POW(ll a,ll b,ll m){    ll ret=1;    while(b)    {        if(b&1)            ret=ret*a%m;        a=a*a%m;        b>>=1;    }    return ret;}int main(){    ll n,m,ans;    while(scanf("%I64d%I64d",&n,&m)!=EOF)    {        if(n&1)        {            ans=(POW(2,n+1,3*m)-1)/3;            printf("%I64d\n",ans);        }        else        {            ans=(POW(2,n+1,3*m)-2)/3;            printf("%I64d\n",ans);        }    }    return 0;}



2、矩阵快速幂

当i是偶数时,a[i]=2*a[i-1](i>=2);

当i是奇数时,a[i]=2*a[i-1]+1(i>=3,a[1]=1)。

进一步可以得到:当i是偶数时,a[i]=2*a[i-1]=4*a[i-2]+2,如果令a[0]=0,则





当i是奇数时,先计算i-1(因为i-1是偶数),再利用a[i]=2*a[i-1]+1。


代码如下:

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <iostream>#include <algorithm>#include <string>#include <vector>#include <deque>#include <list>#include <set>#include <map>#include <stack>#include <queue>#include <numeric>#include <iomanip>#include <bitset>#include <sstream>#include <fstream>#include <limits.h>#define debug "output for debug\n"#define pi (acos(-1.0))#define eps (1e-6)#define inf (1<<28)#define sqr(x) (x) * (x)using namespace std;typedef long long ll;typedef unsigned long long ULL;#define MAX 4ll n,m,mod;struct Matr{    ll w[MAX][MAX];    Matr()    {        memset(w,0,sizeof(w));    }};Matr operator *(Matr a,Matr b){    Matr c;    ll i,j,k;    for(k=1;k<=2;k++)    {        for(i=1;i<=2;i++)        {            if(a.w[i][k]==0)                continue;            for(j=1;j<=2;j++)            {                if(b.w[k][j]==0)                    continue;                c.w[i][j]=(c.w[i][j]+a.w[i][k]*b.w[k][j])%mod;            }        }    }    return c;}Matr operator ^(Matr a,ll k){    Matr c;    ll i,j;    for(i=1;i<=2;i++)        c.w[i][i]=1;    while(k)    {        if(k&1)            c=c*a;        a=a*a;        k>>=1;    }    return c;}int main(){    ll i,j,k;    Matr a,b,c;    while(~scanf("%I64d%I64d",&n,&m))    {        a.w[1][1]=4;a.w[1][2]=1;        a.w[2][1]=0;a.w[2][2]=1;        b.w[1][1]=0;        b.w[2][1]=2;        mod=m;        if(n&1)        {            c=a^((n-1)/2);            printf("%I64d\n",(c.w[1][2]*2*2+1)%mod);        }        else        {            c=a^(n/2);            printf("%I64d\n",c.w[1][2]*2%mod);        }    }    return 0;}



0 0
原创粉丝点击