代码改变世界

hdu3483 A Very Simple Problem

2014-11-12 17:19  达利园大面包  阅读(193)  评论(0)    收藏  举报

理论上高斯消元可以做,实际上我*&%^&%$^&.

理论上可以构造出矩阵,可是我不会,后来看了题解,真是手贱.

有了初始向量很好递推的,由于手贱,没有初始化,WA几发.

-----------------------------------------------------------

#include <cstdio>
#include <cstring>
using namespace std;
long long com[100][100],a[100][100],tmp[100][100];
long long n,x,m;
void quick_pow(long long  k){
    if (k==0){
        memset(a,0,sizeof(a));
        for (int i=0;i<=x+1;i++){
            a[i][i] = 1;
        }
        return ;
    }
    quick_pow(k/2);
    for (int i=0;i<=x+1;i++){
        for (int j=0;j<=x+1;j++){
            tmp[i][j] = 0;
            for (int k=0;k<=x+1;k++){
                tmp[i][j] = (tmp[i][j] + a[i][k] * a[k][j] % m) % m;
            }
        }
    }
    if (k&1){
        for (int i=0;i<=x+1;i++){
            for (int j=0;j<=x+1;j++){
                a[i][j] = 0;
                for (int k=0;k<=x+1;k++){
                    a[i][j] = (a[i][j] + tmp[i][k] * com[k][j] % m) % m;
                }
            }
        }
    }else{
        for (int i=0;i<=x+1;i++){
            for (int j=0;j<=x+1;j++){
                a[i][j] = tmp[i][j];
            }
        }
    }
}
int main(){
    while (scanf("%I64d%I64d%I64d",&n,&x,&m)!=EOF){
        if (n<0||x<0||m<0) break;
        com[0][0] = x % m;
        com[1][0] = x % m;
        com[1][1] = x % m;
        for (int i=2;i<=x;i++){
            com[i][0] = x % m;
            for (int j=1;j<=i;j++){
                com[i][j] = (com[i-1][j-1] + com[i-1][j]) % m;
            }
        }
        for (int i=0;i<x;i++) com[x+1][i] = 0;
        com[x+1][x] = com[x+1][x+1] = 1;
        quick_pow(n);
        long long ans = 0;
        for (int i=0;i<=x;i++) ans = (ans + a[x+1][i]) % m;
        printf("%I64d\n",ans * x % m);
    }
    return 0;
}