CF293B 方格(帶技巧的搜尋)

2022-04-28 19:51:10 字數 1766 閱讀 7151

首先我們根據一條路徑上不能有兩個相同顏色的格仔可以得出:

對於兩個格仔 $ (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以內的所有數的素因子,並用數字標記的方式...