• A Very Simple Problem


    A Very Simple Problem

    Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 88 Accepted Submission(s): 55
     
    Problem Description
    This is a very simple problem. Given three integers N, x, and M, your task is to calculate out the following value:

     
    Input
    There are several test cases. For each case, there is a line with three integers N, x, and M, where 1 ≤ N, M ≤ 2*109, and 1 ≤ x ≤ 50.
    The input ends up with three negative numbers, which should not be processed as a case.
     
    Output

                For each test case, print a line with an integer indicating the result.
     
    Sample Input
    100 1 10000
    3 4 1000
    -1 -1 -1
     
    Sample Output
    5050
    444
     
     
    Source
    2010 ACM-ICPC Multi-University Training Contest(5)——Host by BJTU
     
    Recommend
    zhengfeng
     
    /*
    题意:给你n,x,m,让你求1^x*x^1+2^x*x^2+...+n^x*x^n;
    
    初步思路:刚开始一点思路也没有,看了题解才发现妙处。
    
    #补充:设F[n]=x^n,n*(x^n),(n^2)*(x^n),...,(n^x)*(x^n);
           得到:
             F[n][k]=(n^k)*(x^n);
           则要求的结果为:
             G[n]=F[1][k]+F[2][k]+...+F[n][k];
           设C(i,j)为组合数,即i种元素取j种的方法数 
           所以有:f[n+1][k] = ((n+1)^k)*(x^(n+1)) (二次多项式展开)
                             = x*( C(k,0)*(x^n)+C(k,1)*n*(x^n)+...+C(k,k)*(n^k)*(x^n) ) 
                             = x*( C(k,0)*f[n][0]+C(k,1)*f[n][1]+...+C(k,k)*f[n][k] ) 
           得到递推式就可以用矩阵进行快速幂求解
            |x*1 0................................0|       |f[n][0]|       |f[n+1][0]| 
            |x*1 x*1 0............................0|       |f[n][1]|       |f[n+1][1]| 
            |x*1 x*2 x*1 0........................0|   *   |f[n][2]|   =   |f[n+1][2]| 
            |......................................|       |.......|       |.........| 
            |x*1 x*C(k,1) x*C(k,2)...x*C(k,x) 0...0|       |f[n][k]|       |f[n+1][k]| 
            |......................................|       |.......|       |.........| 
            |x*1 x*C(x,1) x*C(x,2).......x*C(x,x) 0|       |f[n][x]|       |f[n+1][x]| 
            |0................................0 1 1|       |g[n-1] |       | g[ n ]  | 
    */
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll n,x,mod;
    ll c[55][55];
    ll unit;
    /********************************矩阵模板**********************************/
    class Matrix {
        public:
            ll a[55][55];
            int n;
            void init() {
                memset(a,0,sizeof(a));//            #出错
                for(int i=0;i<=n;i++){
                    for(int j=0;j<=i;j++){
                        a[i][j]=x*c[i][j]%mod;
                    }
                }
                a[x+1][x]=a[x+1][x+1]=1;
            }
            Matrix operator +(Matrix b) {
                Matrix c;
                c.n = n;
                for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++)
                        c.a[i][j] = (a[i][j] + b.a[i][j]) % mod;
                return c;
            }
    
            Matrix operator +(int x) {
                Matrix c = *this;
                for (int i = 0; i < n; i++)
                    c.a[i][i] += x;
                return c;
            }
    
            Matrix operator *(Matrix b)
            {
                Matrix p;
                p.n = b.n;   
                memset(p.a,0,sizeof p.a);
                for (int i = 0; i < n; i++)
                    for (int j = 0; j < n; j++)
                    for (int k = 0; k < n; k++)
                        p.a[i][j] = (p.a[i][j] + (a[i][k]*b.a[k][j])%mod) % mod;
                return p;
            }
    
            Matrix power(int t) {
                Matrix ans,p = *this;
                ans.n = p.n;  
                memset(ans.a,0,sizeof ans.a);
                for(int i=0;i<=n;i++){//初始化ans
                    ans.a[i][i]=1;
                }
                while (t) {
                    if (t & 1)
                        ans=ans*p;
                    p = p*p;
                    t >>= 1;
                }
                return ans;
            }
    }init;
    void Init(){//求组合数
        memset(c,0,sizeof c);
        for(ll i=0;i<=x;i++)  
                c[i][0]=c[i][i]=1;  
        for(ll i=2;i<=x;i++)  
            for(ll j=1;j<i;j++)  
                c[i][j]=((ll)c[i-1][j-1]+c[i-1][j])%mod;
        unit=0;
    }
    /********************************矩阵模板**********************************/
    int main(){
        // freopen("in.txt","r",stdin);
        while(scanf("%lld%lld%lld",&n,&x,&mod)!=EOF&&(n>0,x>0,mod>0)){
            Init();//                #ok
            
            // for(int i=0;i<=x;i++){
                // for(int j=0;j<=x;j++){
                    // cout<<c[i][j]<<" ";
                // }
                // cout<<endl;
            // }
            // cout<<endl;
            
            init.n=x+2;
            // cout<<"ok"<<endl;
            init.init();
            
            // for(int i=0;i<=x+1;i++){
                // for(int j=0;j<=x+1;j++){
                    // cout<<init.a[i][j]<<" ";
                // }cout<<endl;
            // }
            
            // cout<<"ok"<<endl;
            init=init.power(n);
            
            // for(int i=0;i<=x+1;i++){
                // for(int j=0;j<=x+1;j++){
                    // cout<<init.a[i][j]<<" ";
                // }cout<<endl;
            // }
            
            for(int i=0;i<=x;i++){
                unit+=( (x*init.a[x+1][i])%mod );
            }
            printf("%lld
    ",(unit+mod)%mod);
        }
        return 0;
    }
  • 相关阅读:
    2018年5月29号(堆排序最小顶)
    2018年5月31号(树状数组)
    2018年5月27号(spfa判断负环)
    2018年6月1号(线段树(1))
    2018年5月28号(差分约束)
    Inno Setup入门(十二)——Pascal脚本(1)
    Inno Setup入门(十六)——Inno Setup类参考(2)
    Inno Setup入门(二十一)——Inno Setup类参考(7)
    Inno Setup入门(十)——操作注册表
    Inno Setup入门(十八)——Inno Setup类参考(4)
  • 原文地址:https://www.cnblogs.com/wuwangchuxin0924/p/6404086.html
Copyright © 2020-2023  润新知