136 lines
3.4 KiB
C++
Executable File
136 lines
3.4 KiB
C++
Executable File
// #define NDEBUG //切换release和debug版本
|
||
|
||
#include <cctype>
|
||
#include <iostream>
|
||
#include <algorithm>
|
||
#include <type_traits>
|
||
#include <sstream>
|
||
|
||
using ull = unsigned long long;
|
||
|
||
template<class T,size_t size>
|
||
struct Array{
|
||
constexpr Array(){};
|
||
constexpr Array(const std::initializer_list<T> list){
|
||
std::copy(list.begin(),list.end(),arr);
|
||
}
|
||
#ifdef NDEBUG
|
||
#define NDB_NOEXCEPT noexcept
|
||
#define NDB_CONSTEXPR constexpr
|
||
#else
|
||
#define NDB_NOEXCEPT
|
||
#define NDB_CONSTEXPR
|
||
#endif
|
||
|
||
NDB_CONSTEXPR T& operator[](const size_t n)NDB_NOEXCEPT{
|
||
// static_assert(noexcept(Array::operator[](0)), "isn't noexcept");
|
||
#ifndef NDEBUG
|
||
if(n>=size){
|
||
std::ostringstream err_oss;
|
||
err_oss<<"\n[array_size]: "<<size<<"\n[Your index]: "<<n<<'\n';
|
||
throw std::runtime_error(err_oss.str());
|
||
}
|
||
#endif
|
||
return arr[n];
|
||
}
|
||
struct Iterator{
|
||
constexpr Iterator(const size_t n,T *const p)noexcept:now{n},p{p}{}
|
||
bool operator!=(const Iterator &that)const noexcept{
|
||
return this->now!=that.now;
|
||
}
|
||
NDB_CONSTEXPR T& operator*()const NDB_NOEXCEPT{
|
||
#ifndef NDEBUG
|
||
if(now>=size){
|
||
std::ostringstream err_oss;
|
||
err_oss<<"[array_size]: "<<size<<" [Your index]: "<<now<<'\n';
|
||
throw std::runtime_error(err_oss.str());
|
||
}
|
||
#endif
|
||
return p[now];
|
||
}
|
||
constexpr Iterator& operator++()noexcept{
|
||
now++;
|
||
return *this;
|
||
}
|
||
constexpr Iterator& operator--()noexcept{
|
||
now--;
|
||
return *this;
|
||
}
|
||
constexpr Iterator operator--(int)noexcept{
|
||
auto old = *this;
|
||
now--;
|
||
return old;
|
||
}
|
||
private:
|
||
size_t now;
|
||
T *const p;
|
||
};
|
||
constexpr Iterator begin()noexcept{
|
||
return Iterator(0,arr);
|
||
}
|
||
constexpr Iterator end()noexcept{
|
||
return Iterator(size,arr);
|
||
}
|
||
private:
|
||
T arr[size];
|
||
};
|
||
|
||
|
||
static const size_t max_n {(size_t)2e3+5};
|
||
ull k, t, n, m;
|
||
Array<Array<ull,max_n>,max_n> c,prefix;
|
||
|
||
static void init(){
|
||
c[0][0] = c[1][0] = c[1][1] = 1;
|
||
for(ull i {2};i<max_n;i++){
|
||
c[i][0]=1;
|
||
for(ull j{1};j<=i;j++){
|
||
c[i][j] = (c[i-1][j-1] + c[i-1][j])%k;
|
||
}
|
||
}
|
||
for(ull i = 2;i<max_n;i++){ //注意这里越界了,这是个bug示例
|
||
for(ull j{1};j<=i;j++){
|
||
prefix[i][j] = prefix[i-1][j]+prefix[i][j-1]-prefix[i-1][j-1] + (c[i][j]==0?1:0);
|
||
}
|
||
prefix[i][i+1] = prefix[i][i];
|
||
}
|
||
}
|
||
|
||
#define NV(v)#v<<" : "<<(v)
|
||
|
||
template<class T>
|
||
struct ReadNumber{
|
||
ReadNumber& operator>>(T &num){
|
||
c=0,w=1,n=0;
|
||
while(!isdigit(c)){
|
||
if constexpr (!std::is_unsigned_v<T>){
|
||
if(c=='-')w=-1;
|
||
}
|
||
c=getchar();
|
||
}
|
||
while(isdigit(c)){
|
||
n=n*10+(c-'0');
|
||
c=getchar();
|
||
}
|
||
num = w*n;
|
||
return *this;
|
||
}
|
||
private:
|
||
char c;
|
||
T w,n;
|
||
};
|
||
|
||
ReadNumber<ull> readull;
|
||
|
||
int main(){
|
||
readull>>t>>k;
|
||
// std::cout<<NV(t)<<'\n'<<NV(k)<<'\n';
|
||
init();
|
||
for(ull i {0};i<t;i++){
|
||
// std::cout<<NV(t)<<'\n'<<NV(k)<<'\n';
|
||
readull>>n>>m;
|
||
// std::cout<<"test\n";
|
||
m = std::min(m,n);
|
||
std::cout<<(prefix[n][m])<<'\n';
|
||
}
|
||
} |