首先我們根據一條路徑上不能有兩個相同顏色的格仔可以得出:
對於兩個格仔 $ (x_1 , y_1 ) $ 和 $ (x_2 , y_2 ) $ 必須滿足:
$ x_1y_2 $
$ x_1>x_2 and y_1所以我們可以據此剪枝,但直接暴搜肯定會超時,我們肯定還有技巧:
根據上面的剪枝我們發現將**以(1,1) -> (n,n) -> (1,2) -> (2,1) -> (n,n-1) -> (n-1,n). . .的順序列舉速度會快很多
現在,我們把初始棋盤中沒有出現過的顏色稱作自由顏色。如果我們有兩個自由顏色: 1 和 2 .假設我們找到了乙個可行的最終棋盤,然後把所有的 1 換成 2 ,所有的 2 換成 1 。容易發現得到的棋盤依然是可行的。
我們把自由顏色排序(隨便怎麼排),如果我們當前沒有用過第 i 個自由顏色,那麼我們就不准碰第 i+1 個自由顏色。到最後計算結果的時候,如果我們用了 x 個自由顏色,而總共有 y 個自由顏色,那麼這個局面對答案的貢獻也就是 y 個數中去取 x 個組成有序排列的數目。
#include#include#include#include#include#include#include#include#include#include#include#include#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int
#define mod 1000000007
#define end
using namespace std;
struct sub[13],c[13],d[11][11];
ll ans;
int n,m,l,k,ti,top,sss;
int se[11],to[11];
int tot[11];
int p[11];
int a[10][10];
int ss[10][10];
bool s[10][10];
inline int qr()
inline void add(int t,int x,int y)
inline bool check(int i,int x,int y)return 1;
}inline void dfs(int t)
rg x=b[t].x,y=b[t].y;
if(s[x][y])
for(rg i=1;i<=to[0];++i)
}if(to[0]==k)return ;
add(++to[0],x,y);
ss[x][y]=to[0];
dfs(t+1);
tot[to[0]]=0;--to[0];
return ;
}inline void bfs()
for(rg o=0,r,i,j;ok) end;
for(rg i=1;i<=n;++i)
for(rg j=1;j<=m;++j)
else
if(!check(ti,i,j))
add(ti,i,j);}}
sss=k-to[0];p[0]=1;
for(rg i=0;i
p[i+1]=p[i]*(sss-i);
if(l==k)
top=0; bfs(); dfs(1);
printf("%lld\n",ans%mod);
return 0;
}
cf 551B 暴力列舉
交換a中字元的位置,求b,c字串在a中出現的最多次數 列舉b出現的次數,然後求出c在a中還可以出現的最大次數,求得最多的次數 關鍵在於如何計算b出現的次數 如下 for int i 0 i 26 i if s1 i sum min sum,ans i s1 i 知道了這個就不會超時了啦,我開始就沒想...
cf 1471 B 最大貢獻
t 組樣例 每組有長度為 n 的陣列 a 和 乙個數 x 下一行 輸入陣列 a 如果a i x 0 那麼就將 x個 a i x 放在陣列的末尾,然後繼續這樣的操作,直到a i x 0時停止 求陣列的和 1.昨天打的比賽,其實題目很簡單,考慮一下每個數的最大貢獻值,然後直接模擬就好,但是不是直接暴力模...
CF 453B狀態壓縮dp
題目鏈結 題意 給你n個數 1 n 100 每個數分別是ai 1 ai 30 問你求乙個數列bi,其中bi間的數兩兩的最大公約數為1 bi可能都是1 且使得 思路 既然bi可以全部取1,那麼每個bi的取值必定不超過30 1 30 59。由此可知我們只要知道60以內的所有數的素因子,並用數字標記的方式...