時間限制:1s
記憶體限制:256mb
【問題描述】
對於乙個1~n的排列,如果滿足第i個數|ai-i|<=k,則稱該排列為k-近似排列。
現在排列的若干位置已經確定,你需要計算剩下的數有多少種排列方法使得形成的排列是k-近似排列。
【輸入】
輸入檔名為count.in。
第一行乙個數t(<=10),表示資料組數
對於每一組資料:
第一行三個數n,m,k,分別表示排列長度、已確定位置的個數和近似引數k
接下來m行,每行兩個數x、y,表示已經確定第x個數是y
【輸出】
輸出檔名為count.out。
對於每組資料輸出一行,包含乙個數,表示方法個數(對1,000,000,007取模)
【輸入輸出樣例】
count.in
count.out
4 1 1
2 3【資料說明】
對於30%的資料,1<=n,m<=10,k<=2
對於50%的資料,1<=n,m<=20,k<=2
對於70%的資料,1<=n<=100000,m<=100,k<=2
對於100%的資料,1<=n<=10^9,m<=100,k<=2
坑啊,題目給的樣例不對,他寫的是2,其實是1.!
小暴力50分
#include#include50分暴力#include
#include
#include
#include
#include
using
namespace
std;
intn,m,k,t;
int a[100009
];bool vis[100009
];long
long
ans;
void dfs(int
x)
if(a[x]) dfs(x+1
);
else
for(int i=max(x-k,1);i<=min(x+k,n);i++)
if(!vis[i])
}return;}
intmain()
dfs(1);
printf(
"%lld\n
",ans);
}return0;
}
也可以用狀壓dp做
定義f[j]為當前位上狀態為j的方案數,j是乙個二進位制數,對一每一位上1代表這個數用過,0代表沒用過。(其實能用二維的,習慣用一維,有個二維**)
對於每個狀態,看看能否和 i-k到i+k中每個數拓展,,能拓展的話,就向更大的數擴充套件。(就是說看看這些數選沒選,沒選過的話就加過去)。
70分還是沒寫出來。。。
#include#include50分狀壓dp-一維#include
#include
using
namespace
std;
const
int p=1000000007
;int f[1
<<20],a[100009
];int
t,n,m,k;
intmain()
memset(f,
0,sizeof
(f));
for(int i=0;i<=k&&i)
for(int i=0;i1;i++)
for(int j=(1
<1;j>=0;j--)
}
printf(
"%d\n
",f[(1
<1
]);
}return0;
}
50分dp
#include#include二維#include
#include
using
namespace
std;
const
int p=1000000007
;int f[20][1
<<20],a[20
];int
t,n,m,k;
intmain()
memset(f,
0,sizeof
(f));
for(int i=0;i<=k&&i)
for(int i=0;i1;i++)
for(int j=0;j
}printf(
"%d\n
",f[n-1][(1
<1
]);
}return0;
}
Tyvj P4876 近似排列計數 50
原題鏈結 用了個搜尋 兩個剪枝 明顯在數字固定的地方 就不要列舉了 然後 如果這個數 只可能在這個位置用上 那就只能用這個數了 include include include include include include include include include include define...
P4071 SDOI2016 排列計數
求有多少種長度為 n 的序列 a,滿足以下條件 1 n 這 n 個數在序列中各出現了一次 若第 i 個數 a i 的值為 i,則稱 i 是穩定的。序列恰好有 m 個數是穩定的 滿足條件的序列可能很多,序列數對 109 7取模。輸入格式 第一行乙個數 t,表示有 t 組資料。接下來 t 行,每行兩個整...
題解 P2606 ZJOI2010 排列計數
題目鏈結 題目大意 求 1 n 的排列 p 中,有多少個排列滿足 forall i in 2,n p i p rfloor 對給定質數 m 取模。分析 p i p rfloor 反過來 forall x,p x,那麼問題變成一棵 n 個節點的完全二叉樹,將數 1 n 分配給每乙個節點,使得每個父節點...