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;
}