NOIP 2016 Senior 4

来源:互联网 发布:2017淘宝刷不了单 编辑:程序博客网 时间:2024/06/10 18:11

题目
这道题。。。其实我第一反应是爆搜。由于组合数的计算有多种公式,思路往往会禁锢,这不,题目故意把公式给了你,让你往这个公式上去想,不超时才怪。。。
在使用该公式进行单行递推时,能够轻松地通过一个点,但是对于10000组测试数据就无能为力了,同时,这种方法还受溢出的限制,因此不可取。如果用这种方法应该能得到60分。

正确的做法应该是使用递推公式。因为递推公式是加法,而通项公式是乘法和除法。加法让求余有了可能。观察发现,题目要求在一开始就输入k,而不是每组数据一个,这更坚定了使用递推公式提前初始化好的信心。

再看数据,发现2000的规模是允许我们以O(n2)的时间复杂度进行初始化的。我们必须要做到查询的时间复杂度降到O(1),才能让初始化有意义(2000*2000也不小了)。
首先我们来看看如何判断一个组合数是不是k的倍数。很简单,模k后判断是否为0即可。接下来就是查询,这时我们应该很自然地想到了二维和数组,到这里这道题就简单了。记住用之前写的暴力多测试几下!!!= =

参考代码(稍慢,可以根据题目给的n,m的最大值进行优化,还可以把long long改成int,因为懒所以我就不改了)

#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <string>#include <stack>#include <queue>#include <deque>#include <map>#include <set>#include <bitset>using std::cin;using std::cout;using std::endl;typedef unsigned long long INT;inline INT readIn(){    INT a = 0;    bool minus = false;    char ch = getchar();    while(!(ch == '-' || ch >= '0' && ch <= '9')) ch = getchar();    if(ch == '-')    {        minus = true;        ch = getchar();    }    while(ch >= '0' && ch <= '9')    {        a *= 10;        a += ch;        a -= '0';        ch = getchar();    }    if(minus) a = -a;    return a;}const INT maxn = 2005;INT mod;INT n, m;INT C[maxn + 5][maxn + 5];INT f[maxn + 5][maxn + 5];void run(){    INT a = readIn();    mod = readIn();    for(int i = 1; i <= maxn; i++)    {        C[i][0] = C[i][i] = 1;        for(int j = 1; j < i; j++)        {            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;        }    }    for(int i = 1; i <= maxn; i++)    {        for(int j = 0; j <= maxn; j++)        {            if(j)            {                f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + (j <= i && !C[i][j]);            }            else            {                f[i][j] = f[i - 1][j] + (j <= i && !C[i][j]);            }        }    }    while(a--)    {        INT ans = 0;        n = readIn();        m = readIn();        cout << f[n][m] << endl;    }}int main(){    run();    return 0;}
原创粉丝点击