China University of Petroleum ACM club jogo-treino aberto --- questão K: problemas matemáticos (pré-tratamento + prefixo e bidimensional)

Pergunta K: problemas de matemática

Prazo: 1 Sec Limite de memória: 128 MB
apresentar: 381 Resolução 24
[ estado ] [ enviar ] [homem proposição: Import External]

título Descrição

Nós aprendemos que o ensino médio é o número de combinações. Assim, dado um inteiro n, m, g, inteligente pode encontrar quantos pares de inteiros (i, j), g meet divisível isso? (Em que 0≤i≤n, 0≤j≤min (i, m) ). (Sugestão: n = 1 × 2 × ⋯ × n; ., Em particular, 0 = 1 !!)

entrada

Uma primeira linha de número inteiro T (t <= 104), indica o número de conjuntos de dados de teste;
segunda fileira um inteiro g (1 <g <= 25 );
O próximo dois inteiros cada linha fileira t n, m (n, m <= 2000);
significado n, m, g ver descrição tópico.

 

exportação

linhas de saída T, cada um, um número inteiro que representa o número de pares de números inteiros (i, j) satisfaz divisível por g (0≤i≤n, 0≤j≤min (i, m )).

entrada de exemplo Copiar

1 
4 
5 4

Exemplo de saída de cópia

2

Um prefixo e s bidimensional [i] [j] = s [I-1] [j] + d [i] [j-1] -s [I-1] [j-1], o (n, m ) dentro de uma gama predeterminada de um número inteiro de pares de mesa de jogo, o optimizador de consulta para cada o (1).

Poços: n possível <m

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 2e3 + 10;

ll a[N][N];
ll sum[N][N];
ll g;

void init()
{
    memset(a, 0, sizeof(a));
    a[0][0] = 1;
    for(int i = 1; i < N; ++i)
    {
        a[i][0] = 1;
        a[i][i] = 1;
        for(int j = 1; j < i; ++j)
        {
            a[i][j] = ((a[i - 1][j] % g) + (a[i - 1][j - 1] % g)) % g;
        }
    }
}

void solve()
{
    memset(sum, 0, sizeof(sum));
    for(int i = 1; i < N; ++i)
    {
        for(int j = 1; j <= i; ++j)
        {
            sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
            if(a[i][j] == 0)
            {
                sum[i][j]++;
            }
        }
        sum[i][i + 1] = sum[i][i];
    }
}

int main()
{
    int n, t, m;
    while(~scanf("%d", &t))
    {
        scanf("%lld", &g);
        init();
        solve();
        while(t--)
        {
            scanf("%d%d", &n, &m);
            if(n < m)
                m = n;
            cout<<sum[n][m]<<'\n';
        }
    }
    return 0;
}

 

Ele publicou 188 artigos originais · ganhou elogios 13 · vista 10000 +

Acho que você gosta

Origin blog.csdn.net/weixin_43871207/article/details/104747838
Recomendado
Clasificación