jzoj 6301. 普及组

Posted jz929

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jzoj 6301. 普及组相关的知识,希望对你有一定的参考价值。

Description

详见OJ

Solution

感觉这题是最神仙的。。。
考场\(AC\)的人说自己是暴力枚举转移方程而得到了一个正确的转移式。
对于数据中的\(x\),我们发现分解质因数后,每个质因数的指数最大是\(2\)

当指数为\(1\)的时候,很容易得出答案乘以\(n!\)(因为每列每行都只能有一个这个质数)
当指数为\(2\)的时候,那人通过暴枚得出\(f[i]=i*i*f[i-1]+i*(i-1)*(i-1)/2*f[i-2]\),答案乘以\(f[n]\)
最后再乘以\(2^(n-1)*(n-1)\)即可。

Code

#include <cstdio>
#define N 5000000
#define ll long long
#define mo 998244353
#define mem(x, a) memset(x, a, sizeof x)
#define fo(x, a, b) for (int x = a; x <= b; x++)
#define fd(x, a, b) for (int x = a; x >= b; x--)
using namespace std;
int T, n, cs[31][2], tot = 0;
ll x, f[N + 10], jc[N + 10], tot1 = 0, tot2 = 0;

inline int read()

    int x = 0; char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return x;


ll ksm(ll x, int y)

    ll s = 1;
    while (y)
    
        if (y & 1) s = s * x % mo;
        x = x * x % mo; y >>= 1;
    
    return s;


int main()

    freopen("pj.in", "r", stdin);
    freopen("pj.out", "w", stdout);
    scanf("%lld", &x);
    fo(i, 2, 3000)
        if (x % i == 0)
        
//          cs[++tot][0] = i;
            tot = 0;
            while (x % i == 0)
                x /= i, tot++;
            if (tot == 1) tot1++;
            else tot2++;
        
    if (x > 1) tot1++;
    f[1] = 1, f[2] = 3; jc[1] = 1, jc[2] = 2;
    for (ll i = 3; i <= N; i++)
    
        f[i] = (i * i % mo * f[i - 1] % mo - i * (i - 1) / 2 % mo * (i - 1) % mo * f[i - 2] % mo + mo) % mo;
        jc[i] = jc[i - 1] * i % mo;
    
    T = read();
    while (T--)
    
        n = read();
        printf("%d\n", ksm(jc[n], tot1) * ksm(f[n], tot2) % mo * ksm(2, (ll)(n - 1) * (n - 1) % (mo - 1)) % mo);
    
    return 0;

以上是关于jzoj 6301. 普及组的主要内容,如果未能解决你的问题,请参考以下文章

noip2006普及组测评数据

急求NOIP2009普及组试题

NOIP2006普及组开心的金明

2006NOIP普及组试题

悬赏!急!pascal竞赛普及组模拟试题

06普及组开心的金明程序思路