[HAOI2011] problem C
2286 ワード
タイトルの説明
n人に席を手配して、まず一人に1~nの番号を付けて、i人目の番号をai(異なる人の番号は同じでもいい)にして、それから1人目から順番に席に着いて、i人目が来たらaiに座ってみて、aiが占拠されたらai+1を試して、ai+1も占拠されたらai+2を試して、・、n人目まで試してもだめなら、この手配案は合法ではない.しかし、m個人の番号はすでに確定しています(彼らはあなたの上司に賄賂を渡したかもしれません...).残りの人の番号を手配するしかありません.合法的な手配案を求めます.答えは大きいかもしれないので、Mで割った残りの数を出力するだけでいいです.
にゅうしゅつりょくけいしき
入力形式:
1行目の整数Tは、データ群数を表す
各データのセットについて、最初の行にはn、m、Mの3つの整数があります.
mが0でなければ、次の行にm対の整数があり、p 1、q 1、p 2、q 2、...、pm、qmであり、i対目の整数pi、qiが第pi個人を表す番号はqiでなければならない
出力フォーマット:
データのセットごとに1行ずつ出力し、解があればYESを出力し、整数でシナリオ数mod Mを表す.ただし、YESと数の間にはスペースが1つしかない.そうでなければNOを出力する
入出力サンプル
サンプル#1を入力:
出力サンプル#1:
説明
100%のデータは、1≦T≦10、1≦n≦300、0≦m≦n、2≦M≦10^9、1≦pi、qi≦nを満たし、piが互いに異なることを保証する.
s[i]を前のi個の位置としていくつかの人選された場合、1つのスキームが合法的であり、すべてのiに対してs[i]>=iである場合にのみ発見される.
したがって,人選の順序を考慮するのではなく,位置dp,f[i][j]に従って前のi個の位置がj個の人選されたシナリオ数を表し,さらにO(N)を移すことができる.
では、もし誰かが席を予約したら?p[i]を前のiの位置に欽定された人数とすると、f[i][j]は合法的であり、j+p[i]>=iのみである.
転載先:https://www.cnblogs.com/JYYHH/p/8793868.html
n人に席を手配して、まず一人に1~nの番号を付けて、i人目の番号をai(異なる人の番号は同じでもいい)にして、それから1人目から順番に席に着いて、i人目が来たらaiに座ってみて、aiが占拠されたらai+1を試して、ai+1も占拠されたらai+2を試して、・、n人目まで試してもだめなら、この手配案は合法ではない.しかし、m個人の番号はすでに確定しています(彼らはあなたの上司に賄賂を渡したかもしれません...).残りの人の番号を手配するしかありません.合法的な手配案を求めます.答えは大きいかもしれないので、Mで割った残りの数を出力するだけでいいです.
にゅうしゅつりょくけいしき
入力形式:
1行目の整数Tは、データ群数を表す
各データのセットについて、最初の行にはn、m、Mの3つの整数があります.
mが0でなければ、次の行にm対の整数があり、p 1、q 1、p 2、q 2、...、pm、qmであり、i対目の整数pi、qiが第pi個人を表す番号はqiでなければならない
出力フォーマット:
データのセットごとに1行ずつ出力し、解があればYESを出力し、整数でシナリオ数mod Mを表す.ただし、YESと数の間にはスペースが1つしかない.そうでなければNOを出力する
入出力サンプル
サンプル#1を入力:
2
4 3 10
1 2 2 1 3 1
10 3 8882
7 9 2 9 5 10
出力サンプル#1:
YES 4
NO
説明
100%のデータは、1≦T≦10、1≦n≦300、0≦m≦n、2≦M≦10^9、1≦pi、qi≦nを満たし、piが互いに異なることを保証する.
s[i]を前のi個の位置としていくつかの人選された場合、1つのスキームが合法的であり、すべてのiに対してs[i]>=iである場合にのみ発見される.
したがって,人選の順序を考慮するのではなく,位置dp,f[i][j]に従って前のi個の位置がj個の人選されたシナリオ数を表し,さらにO(N)を移すことができる.
では、もし誰かが席を予約したら?p[i]を前のiの位置に欽定された人数とすると、f[i][j]は合法的であり、j+p[i]>=iのみである.
#include
#define ll long long
using namespace std;
const int maxn=305;
int n,m,P,s[maxn],pos,lef,T;
int C[maxn][maxn],f[maxn][maxn];
inline int add(int x,int y){
x+=y;
return x>=P?x-P:x;
}
inline void init(){
memset(f,0,sizeof(f));
memset(s,0,sizeof(s));
C[0][0]=1;
for(int i=1;i<=300;i++){
C[i][0]=1;
for(int j=1;j<=i;j++) C[i][j]=add(C[i-1][j-1],C[i-1][j]);
}
}
inline void dp(){
for(int i=1;i<=n;i++) s[i]+=s[i-1];
f[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=max(0,i-s[i]);j<=lef;j++)
for(int l=0;l<=j;l++) f[i][j]=add(f[i][j],f[i-1][l]*(ll)C[lef-l][j-l]%P);
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&P),lef=n-m;
init();
for(;m;m--) scanf("%d",&pos),scanf("%d",&pos),s[pos]++;
bool flag=1;
for(int i=1,tot=0;i<=n;i++){
tot+=s[n-i+1];
if(tot>i){
flag=0,puts("NO");
break;
}
}
if(!flag) continue;
dp();
printf("YES %d
",f[n][lef]);
}
return 0;
}
転載先:https://www.cnblogs.com/JYYHH/p/8793868.html