NOIP2016Day2T1 nombre de combinaisons problème Luo Gu p2822 résolution rapport

Voir le titre original Luo Valley ( https://www.luogu.org/problem/show?pid=2822 )
NOIP le deuxième jour du premier titre à utiliser la connaissance de la théorie des nombres:
50 points algorithme
approche la plus violente est l'utilisation directe de formule, chercher Qu'est - ce que la table factoriel de jeu
65 points algorithme
sur la base de l'énumération de la violence, le nombre de combinaisons d'autres côté de l' ordinateur par côté, un ensemble unique de la complexité des données en temps O (n ^ 3)
une optimisation plus poussée de la violence (haute précision) (score le plus élevé : 75)
côte à côte avec une grande précision , en plus de passagers de haute précision lorsque la violence sur la base de l'énumération, compter le nombre de combinaisons, un ensemble unique de la complexité du temps de données O (n) ,
mais l' espace d'éclatement de puissance, en fonction du nombre de bits stockés dans votre combien

90 points algorithme
on compte les combinaisons et relation un à un entre le triangle de Pascal triangle de Pascal peut tirer formule récursive est probablement f [i, j] = f [i-1, j] + f [i-1, j-1 ] avant de l'ensemble du réseau est initialisé à 0, alors f [i, 0] = 1 (i = 0 à max) pour faire une initialisation, la relation entre le nombre et la combinaison du triangle de Pascal est un Cij = f [i, j] lorsque la table de jeu pour chaque numéro k modulo le triangle de Pascal, à savoir f [i] [j] = f [i-1] [j]% k + f [i-1] [j-1] % k = (f [i- 1] [j] + f [i-1] [j-1]) chaque i de 0 à n, j min (i, m ) pour éliminer le courant après un nombre de 0% k Si f [i] [j] == 0 alors count ++, après une sortie de comptage fait comme cela peut approcher 10 et 13 points sur. Premier code affiché:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int num[2005][2005];
int sum[2005][2005];
int k,t,m,n;
void deal(){
    memset(num,0,sizeof(num));
    for(int i=0;i<=2002;i++){
        num[i][0]=1;
    }
    for(int i=1;i<=2002;i++){
        for(int j=1;j<=i;j++){
            num[i][j]=(num[i-1][j]+num[i-1][j-1])%k;
        }
    }
}
int main()
{
    memset(sum,0,sizeof(sum));
    int count=0;
    scanf("%d%d",&t,&k);
    deal();
    for(int r=0;r<t;r++){
        scanf("%d%d",&m,&n);
        for(int i=0;i<=m;i++){
            for(int j=0;j<=min(i,n);j++){
                if(num[i][j]==0){
                    count++;
                }
            }
        }
        printf("%d\n",count);
        count=0;

    }
    return 0;
}

100 algorithme
préfixe dimensions et de traitement, après chaque complexité du temps de retrait est O (1), ainsi la durée totale est d' environ 3 fois 90 fois , mais cette question peut être AC (3110ms)
parler maintenant sur les préfixes et les questions:

Préfixe et une dimension

Cette optimisation est principalement utilisée dans une séquence déterminée, a [i] + a [ i + 1] + ...... + a [j] et O (1) heure.
DÉTAILLÉE principe simple: une somme [i] représente (a [1] + a [ 2] + ...... + a [i]), dans lequel la somme [0] = 0, alors (a [i] + a [ i + 1] + ...... + a [j ]) qui est égale à la somme [j] -sum [i- 1].

Et préfixe à deux dimensions

De même, il y a deux dimensions à une dimension. Une matrice pour un, on peut déterminer la sous-matrice [x1 x2 ~] [~ y1 y2] O (1) et le temps.

à condition que la somme [i] [j] est la sous-matrice [1 ~ i] [1 ~ j] et. Par le principe d'inclusion-exclusion était:

somme [0] [j] = somme [i] [0] = 0

un [x1 x2 ~] [~ y1 y2] = somme [x2] [y2] -sum [x 1-1] [y2] -sum [x2] [Y1-1] + somme [x 1-1] [Y1-1 ]

problèmes d'application

Base deux mots: réduction de la dimensionnalité.

Face à de nombreux problèmes de grande dimension, souvent préfixe et la méthode de réduction dimension est d' abord pensé.
Sur la base d' une telle réduction de la dimension sur la poursuite de l' optimisation peut être atteint.
Nous utilisons maintenant le préfixe et pré-traitement de chaque résultat, chaque fois que la sortie très bien

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 2016;
int num[MAXN][MAXN];
int sum[MAXN][MAXN];
int main()
{
    int T,k;
    scanf("%d%d",&T,&k);
    for(int i=0;i<MAXN;i++){
        num[i][0]=0;
        num[0][i]=1;
    }
    for(int i=1;i<MAXN;i++){
        for(int j=1;j<MAXN;j++){
            num[i][j]=(num[i][j-1]+num[i-1][j-1])%k; 
        }
    }
    for(int i=1;i<MAXN;i++){
        for(int j=1;j<i;j++){
            sum[j][i]=sum[j-1][i]+sum[j][i-1]-sum[j-1][i-1];
            if (num[j][i]==0){
                sum[j][i]++;
            } 
        }
        sum[i][i]=sum[i-1][i];          
        if(num[i][i]==0){
            sum[i][i]++;
        } 
    }
    for(int i=0;i<T;i++){
        int n,m;        
        scanf("%d%d",&n,&m);
        while(m>n){
            m--;
        }
        printf("%d\n",sum[m][n]);
//题目说明了0 <= j <= min(i,m),也就是m应要<=n; 
    }
    return 0;
}
Publié 41 articles originaux · louange gagné 58 · vues + 60000

Je suppose que tu aimes

Origine blog.csdn.net/a1351937368/article/details/76907902
conseillé
Classement