暑假集训 || 数论初步

 

·矩阵 (结构体)

struct Matrix
{
    long long a[SZ][SZ];
    friend Matrix operator * (Matrix x, Matrix y)
    {
        Matrix ans;
        memset(ans.a, 0, sizeof(ans.a));
        for(int i = 0; i < SZ; i++)
            for(int j = 0; j < SZ; j++)
                for(int k = 0; k < SZ; k++)
                    ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;
        return ans;
    }
};
Matrix mpow(Matrix x, int y)
{
    Matrix ans;//ans初始化成单位矩阵Ek
    memset(ans.a, 0, sizeof(ans.a));
    for(int i = 0; i < SZ; i++) ans.a[i][i] = 1;
    while(y)
    {
        if(y&1) ans = x * ans;
        y >>= 1;
        x = x * x;
    }
    return ans;
}
 
构造矩阵新技能√
 
 
 
·费马小定理
 
 
·欧拉定理
 
 
·素数
 
欧拉筛 O(nlogn)
void getprime(int n)
{
    memset(isprime, true, sizeof(isprime));
    memset(prime, 0, sizeof(prime));
    isprime[0] = isprime[1] = 0;
    int cnt = 0;
    for(int i = 2; i <= n; i++)
    {
        if(isprime[i]) prime[cnt++] = i;
        for(int j = 0; j<cnt && prime[j]*i <= n; j++)
        {
            isprime[prime[j]*i] = false;
            if(!(i % prime[j])) break;
        }
    }
}
View Code
 
欧拉函数
求前n个数欧拉函数,phi[i]比i小的与i互质的数的个数
void getphi(int n)
{
    memset(isprime, true, sizeof(isprime));
    memset(prime, 0, sizeof(prime));
    isprime[0] = isprime[1] = 0;
    int cnt = 0;
    for(int i = 2; i <= n; i++)
    {
        if(isprime[i]) prime[cnt++] = i, phi[i] = i-1;
        for(int j = 0; j<cnt && prime[j]*i <= n; j++)
        {
            isprime[prime[j]*i] = false;
            if(!(i % prime[j]))
            {
                phi[i*prime[j]] = phi[i] * prime[j];
                break;
            }
            else phi[i*prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
}
View Code
 
·逆元
 
求x在模p下的逆元y
 
 
 
 
 
HDU 5950
题意:f[0]=a, f[1]=b,x>=2时,f[x] = 2*f[x-2] + f[x-1] + x^4
对 1 i i2 i3 i4 f[n-2] f[n-1] 构造矩阵
1 1 1 1 1 0 1
0 1 2 3 4 0 4
0 0 1 3 6 0 6
0 0 0 1 4 0 4
0 0 0 0 1 0 1
0 0 0 0 0 0 2
0 0 0 0 0 1 1
两者乘完能得到 1 (i+1)^2 (i+1)^3 (i+1)^4 f[n-1] f[n](=2*f[n-2] + f[n-1] + n^4)
矩阵乘法做完要输出结果哇 发现是从x=2开始做的 所以把i+1代成2(初始)再和矩阵乘一下得到的右下角f[n]就是结果
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define mod 2147493647
#define SZ 7
long long a, b;
struct Matrix
{
    long long a[SZ][SZ];
    friend Matrix operator * (Matrix x, Matrix y)
    {
        Matrix ans;
        memset(ans.a, 0, sizeof(ans.a));
        for(int i = 0; i < SZ; i++) //SZ是矩阵的大小
            for(int j = 0; j < SZ; j++)
                for(int k = 0; k < SZ; k++)
                    ans.a[i][j] = (ans.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;
        return ans;
    }
};
Matrix mpow(Matrix x, int y)
{
    Matrix ans;//ans初始化成单位矩阵Ek
    memset(ans.a, 0, sizeof(ans.a));
    for(int i = 0; i < SZ; i++) ans.a[i][i] = 1;
    while(y)
    {
        if(y&1) ans = x * ans;
        y >>= 1;
        x = x * x;
    }
    return ans;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d %lld %lld", &n, &a, &b);
        if(n == 1) {printf("%lld\n", a); continue;}
        if(n == 2) {printf("%lld\n", b); continue;}
        Matrix m;
        memset(m.a, 0, sizeof(m.a));
        m.a[0][0]=m.a[0][1]=m.a[0][2]=m.a[0][3]=m.a[0][4]=m.a[0][6]=m.a[1][1]=m.a[2][2]=m.a[3][3]=m.a[4][4]=m.a[4][6]=m.a[6][5]=m.a[6][6]=1;
        m.a[1][2]=m.a[5][6]=2;
        m.a[1][3]=m.a[2][3]=3;
        m.a[1][4]=m.a[1][6]=m.a[3][4]=m.a[3][6]=4;
        m.a[2][4]=m.a[2][6]=6;
        Matrix res = mpow(m, n-2);
        printf("%lld\n", (res.a[0][6] + res.a[1][6]*2 + res.a[2][6]*4 + res.a[3][6]*8 + res.a[4][6]*16 + res.a[5][6] * a % mod + res.a[6][6] * b % mod) % mod);
    }
    return 0;
}
View Code

 

posted @ 2018-08-28 22:20  舒羽倾  阅读(120)  评论(0编辑  收藏  举报