t1:
帶權並查集。每個約束看做一條x連向y的邊,邊權為x+y = c
對於乙個x,可能有多個y與他有關係,間接可以算出y與y』的關係,那麼邊權就記為y - y'
每次加入條件,就看看是否衝突
細節詳見**
據說正解是差分約束??苟蒻是真不會。。
#include#include#includeusing namespace std;
const int maxn = 1e3 + 10;
int n,m,k,fa[maxn*2],va[maxn*2],x[maxn],y[maxn],c[maxn];
int fat(int now)
int main()
}else
} if (flag) printf("yes\n");
} return 0;
}
t2:
如果n == 1
以任意位置i作為第乙個,那麼還需要向上刷i-1次,向下刷m-i次
我們可以在m-i次的過程中任意插入i-1個向上刷的操作
即m-i個數之間放入i-1塊隔板(板可以在序列前、後、中間任意位置)
板與物品共有m-i+i-1 = m-1個 於是c(m-1,i-1)
列舉i,統計答案
如果 n == 2
f[i]:刷一面2*i的牆,強制規定第一次必須刷第一行的方案數
f[i] = 2*f[i-1]*(2*i-1)
首先,第一次有兩種刷法,然後要刷完底下2*(i-1)個,而還有第一行的另乙個沒有刷,這塊牆壁可以在刷底下2*(i-1)塊的過程中的任意時刻刷,於是有(2*i-1)個時刻可以刷
統計答案
第一次任意在第i行刷
只刷上面有f[i-1]種,只刷下面有f[m-i]種
上下都刷(隔板法)有c(m-2,2*(i-1))*f[i-1]*f[m-i]種
在這個過程中隨時可以插入刷i行的另一塊的操作
所以 2*c(m-2,2*(i-1))*f[i-1]*f[m-i]*(2*m-1)
#include#include#include#include#include#include#include#include#include#includeusing namespace std;
const int maxn = 3010;
typedef int ll;
const ll mo = 1000000007ll;
ll c[maxn*2][maxn*2],f[maxn];
int n,m,t;
int main()
cin >> t;
while (t--)
else
int ans = ans;
printf("%d\n",ans);
} return 0;
}
t3:
先建立ac自動機
考慮在ac自動機上dp
f[i][j]:原串走到第i個位置,ac自動機走到第j個點,最少需要更改幾個
為了最小化ans,需要盡量貼著原序列走,儘管這樣很容易碰到禁止的序列
列舉j的四個兒子,如果該兒子等於i+1位置上的字母
f[i+1][son] = f[i][j]
否則 f[i+1][son] = f[i][j]+1
當然,原來的ac自動機中有些點一定不能到達的,標出來即可
在轉移失配邊時要注意用|運算,標出字尾為禁止序列的情況(詳見**)
最後,ac自動機以1為根,對於走到0的情況,四個孩子都寫1,否則會出錯啊gg
#include#include#include#include#include#include#include#include#include#includeusing namespace std;
const int maxn = 2e3 + 20;
const int inf = ~0u>>1;
struct ac
}tree[maxn];
struct p
};int g[maxn][maxn];
int n,len,cur = 1,ans = inf,num[maxn],f[maxn];
char c[maxn];
queue q;
queue q;
int change(int pos)
int main()
tree[x].va = 1; }
q.push(1); for (int i = 1; i <= 4; i++) tree[0].ch[i] = 1;
while (!q.empty())
int v = f[k];
while (v && !tree[v].ch[i]) v = f[v];
f[u] = tree[v].ch[i];
tree[u].va |= tree[f[u]].va;
q.push(u);
} }scanf("%s",c+1); len = strlen(c+1);
for (int i = 1; i <= len; i++) num[i] = change(i);
for (int i = 0; i <= len; i++)
for (int j = 0; j <= cur; j++)
g[i][j] = inf;
q.push(p(0,0)); g[0][0] = 0;
while (!q.empty())
if (num[k.x+1] != i && g[k.x+1][tree[k.y].ch[i]] > g[k.x][k.y] + 1)
} }
for (int i = 0; i <= cur; i++) ans = min(ans,g[len][i]);
if (ans == inf) cout << -1;
else cout << ans;
return 0;
}
2016長樂夏令營 Day4
t1 模擬。開一排const char include include include include include include include include includeusing namespace std const char n0 5 3 const char n1 5 3 con...
開源夏令營(9)總結
category.php的製作 php 功能 判斷是否為分類目錄別名,如果不是,則使用category default.php 分類目錄模板 如果是,則使用對應的分類目錄模板 if is category pic elseif 結束 如果訪問其他分類,則使用category default.php ...
演算法營day9
題目描述 乙個整型陣列裡除了兩個數字之外,其他的數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。思路 如果乙個陣列中,只有乙個數字出現一次的話,求這個數的?將序列中的所有數字異或,因為相同的數字異或會為0,乙個不為0的數字異或還是這個數字本身。這個題可以轉換為上述的題,將序列中的所有數字異或,...