組合せ、多くの問題問題解決P2822

この質問出典:グループDay2T1を改善NOIP2016

(\ 90 \)アプローチを指す:最初と\(パスカル\)式ダイ\(K \)センスで\(O(2000 ^ 2) \) 全データ範囲の組み合わせの前処理数。各クエリ、暴力的な列挙のために\(私は\)\(J \)の値、モードならば\(K \) この時点では、の意味がある\(\ ^ J C_I = 0 \)を、説明した\(\をC_I ^ jは\)がある\(K \)倍数。答えるために暴力や更新された統計。

\(コード:\)

#include<bits/stdc++.h>//P2822 组合数问题
using namespace std;
#define re register
#define ll long long
#define il inline
#define dou double
#define un unsigned
il int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
#define INF 114514114
#define clr(x) memset(x,0,sizeof(x))
#define N 2000+10
#define M 2000+10
#define T 10000+10
int t,k,ans;
int n[T],m[T];
ll C[N][M];
il void pascal()
{
    for(re int i=0;i<=2000;i++)
    {
        C[i][0]=1;
        for(re int j=1;j<=i;j++)
            C[i][j]=(C[i-1][j]%k+C[i-1][j-1]%k)%k;
    }
}
int main()
{
    t=read();k=read();
    pascal();
    for(re int i=1;i<=t;i++)
    {
        ans=0;
        n[i]=read();m[i]=read();
        for(re int j=0;j<=n[i];j++)
        {
            for(re int k=0;k<=min(j,m[i]);k++)
            {
                if(C[j][k]==0)ans++;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

\(100 \)アプローチポイント:最初と\(パスカル\)式ダイ\(K \)センスで\(O(2 ^ 2000) \) 全データ範囲の組み合わせの前処理数。各クエリに対して、以降\(0 \のLeq IはnのLeq \ \) そう\(0 \当量J \当量分(I、M)は\) と等価である\(0 \当量J \当量分(nは、M)\) すなわち、我々は唯一のことは必要であり、\(0 \のLeqは、IはnのLeq \を\)、\ (0 \のLeq J \のLeq分(N、M)\)の範囲内の数の回答。

暴力列挙もし\(私は\)\(jは\)と暴力の統計更新答え遅すぎます。二次元の接頭辞とメンテナンスを使用することを検討してください。あなたは使用することができます\(パスカル\)を二次元の接頭辞を維持し、連立方程式の組み合わせの数の値を見つけます。オーダー\(S [X] [Y ] \) を表し\(0 \のLeq I \のLeq X \)を、\ (0 \のLeq J \のLeq Y \)の範囲内の回答の数は、転移\(S [ X] [Y] = sで[ X-1] [Y] + S [X] [Y-1] -s [X-1] [Y-1] + [C [X] [Y] == 0] \) 。 最後に、出力\(S [N] [分 (N、M)] \) 値。

\(コード:\)

#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
#define il inline
#define dou double
#define un unsigned
il int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
#define INF 114514114
#define clr(x) memset(x,0,sizeof(x))
#define N 2000+10
#define M 2000+10
#define T 10000+10
int t,k,n,m;
int c[N][M],s[N][M];
il void pascal()
{
    for(re int i=0;i<=2000;i++)
    {
        c[i][0]=1;
        for(re int j=1;j<=i;j++)
        {
            c[i][j]=(c[i-1][j]%k+c[i-1][j-1]%k)%k;
            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
            if(c[i][j]==0)s[i][j]++;
            s[i][j+1]=s[i][j];
        }
    }
}
int main()
{
    t=read();k=read();
    pascal();
    for(re int i=1;i<=t;i++)
    {
        n=read();m=read();
        cout<<s[n][min(n,m)]<<endl;
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/Hakurei-Reimu/p/11485570.html