A HDU - 4324
https://cn.vjudge.net/problem/30578/origin
找一个有向三元环
因为是一个竞赛图
所以三个点之间的关系只有两种
对于不合法的第一种可以通过一个点的入度计算出来
总共有C(n,3)个关系
那么剩下的关系就是三元环的关系
char s[maxm][maxm];
int inp[maxm];
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
int T;
in(T);
r1(i,T) {
printf("Case #%d: ",i);
int n;
in(n);
r1(i,n)ss(s[i]+1),inp[i] = 0;
r1(i,n)r1(j,n){
if(s[i][j]=='0')continue;
++inp[j];
}
ll tot = 1LL*n*(n-1)*(n-2)/6;
r1(i,n){
ll sz = inp[i];
tot -= sz*(sz-1)/2;
}
if(tot)puts("Yes");
else puts("No");
}
return 0;
}
B HDU - 3521
https://cn.vjudge.net/problem/10888/origin
阶乘增长很快并且只要求输出两位小数而且时限很长
直接暴力个几十次
double m[111][111];
double a[111][111];
double c[111][111];
double b[111][111];
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
int n;
while(~sd(n))
{
if(!n)break;
double ans = 0;
r1(i,n)r1(j,n)sf(a[i][j]);
r1(i,n)r1(j,n)m[i][j] = a[i][j];
r1(i,n)r1(j,n)b[i][j] = (i==j);
r1(t,100)
{
r1(i,n)r1(j,n)b[i][j] += (m[i][j]/=t);
r1(i,n)r1(j,n)c[i][j] = 0;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
for(int k=1;k<=n;++k)
c[i][j] += m[i][k]*a[k][j];
r1(i,n)r1(j,n)m[i][j] = c[i][j];
}
r1(i,n){
r1(j,n)printf("%.2f ",b[i][j]);
puts("");
}
}
return 0;
}
C HDU - 3913
https://cn.vjudge.net/problem/21551/origin
给定一个字符串和要求的后缀字典序排名
问改成符合排名最少需要改变几个字母
dp[ i ] [ j ]表示满足前i个排名的后缀并且当前第i个后缀起始字符为j
保证了下一位序的大小关系 所以可以dp
int rk[maxm],sa[maxm];
char s[maxm];
int dp[maxm][30];
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
int n;
while(~sd(n)) {
ss(s);
r0(i,n)sd(sa[i]),rk[sa[i]] = i;
rk[n] = -1;
mst(dp,0x3f);
r0(i,26)dp[0][i] = (s[sa[0]]!='a'+i);
for(int i=1; i<n; ++i) {
for(int j=0; j<26; ++j) {
int cost = (s[sa[i]]!='a'+j);
for(int k=0; k<j; ++k) {
dp[i][j] = min(dp[i][j],dp[i-1][k] + cost);
}
if(rk[sa[i-1]+1]<rk[sa[i]+1])dp[i][j] = min(dp[i][j],dp[i-1][j]+cost);
}
}
int ans = inf;
for(int i=0;i<26;++i)
ans = min(ans,dp[n-1][i]);
if(ans==inf)ans = -1;
ansn();
}
return 0;
}
D HDU - 3973
https://cn.vjudge.net/problem/22740/origin
hash字典树
需要注意找一个好的mod数
(这里试过了1e9+7和19660813都可以过
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <queue>
#include <cstdio>
#include <map>
#include <set>
#include <utility>
#include <stack>
#include <cstring>
#include <cmath>
#include <vector>
#include <ctime>
#include <bitset>
#include <assert.h>
using namespace std;
#define pb push_back
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define ansn() printf("%d\n",ans)
#define lansn() printf("%lld\n",ans)
#define r0(i,n) for(int i=0;i<(n);++i)
#define r1(i,e) for(int i=1;i<=e;++i)
#define rn(i,e) for(int i=e;i>=1;--i)
#define mst(abc,bca) memset(abc,bca,sizeof abc)
#define lowbit(a) (a&(-a))
#define all(a) a.begin(),a.end()
#define pii pair<int,int>
#define pll pair<long long,long long>
#define mp(aa,bb) make_pair(aa,bb)
#define lrt rt<<1
#define rrt rt<<1|1
#define X first
#define Y second
#define PI (acos(-1.0))
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
//const ll mod = 1000000007;
const double eps=1e-12;
const int inf=0x3f3f3f3f;
//const ll infl = 100000000000000000;//1e17
const int maxn= 2e6+20;
const int maxm = 5e3+20;
//muv[i]=(p-(p/i))*muv[p%i]%p;
int in(int &ret) {
char c;
int sgn ;
if(c=getchar(),c==EOF)return -1;
while(c!='-'&&(c<'0'||c>'9'))c=getchar();
sgn = (c=='-')?-1:1;
ret = (c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9')ret = ret*10+(c-'0');
ret *=sgn;
return 1;
}
int mod = 1000000007;
int ha[100000+10];
int key = 131;
map<int,bool>ma;
char s[2000000+20];
int seg[100005<<2];
void build(int rt,int l,int r) {
if(l==r) {
seg[rt] = s[l];
return ;
}
int mid = (l+r)>>1;
build(lrt,l,mid);
build(rrt,mid+1,r);
seg[rt] = ((1LL*seg[lrt]*ha[r-mid])%mod + seg[rrt])%mod;
}
void update(int rt,int l,int r,int p,int v) {
if(l==r) {
seg[rt] = v;
return ;
}
int mid = (l+r)>>1;
if(p<=mid)update(lrt,l,mid,p,v);
else update(rrt,mid+1,r,p,v);
seg[rt] = ((1LL*seg[lrt]*ha[r-mid])%mod + seg[rrt])%mod;
}
int query(int rt,int l,int r,int L,int R) {
if(L<=l&&R>=r)return 1LL*seg[rt]*ha[R-r]%mod;
int res = 0;
int mid = (l+r)>>1;
if(L<=mid)res += query(lrt,l,mid,L,R);
if(R>mid)res = (1LL*res + query(rrt,mid+1,r,L,R))%mod;
return res;
}
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
ha[0] = 1;
for(int i=1; i<=100000; ++i)ha[i] = (1LL*ha[i-1]*key)%mod;
int t;
sd(t);
r1(cas,t) {
printf("Case #%d:\n",cas);
ma.clear();
int n;
sd(n);
while(n--) {
ss(s+1);
int len = strlen(s+1);
int u = 0;
for(int i=1; i<=len; ++i)
u = (1LL*u*key%mod + s[i]) %mod;
ma[u] = 1;
// cout<<u<<endl;
}
ss(s+1);
n = strlen(s+1);
build(1,1,n);
int m;
sd(m);
while(m--) {
char op[5];
ss(op);
if(op[0]=='Q') {
int l,r;
sdd(l,r);
++l,++r;
int q = query(1,1,n,l,r);
// cout<<q<<endl;
if(ma.count(q))puts("Yes");
else puts("No");
} else {
char str[5];
int x;
sd(x);
ss(str);
++x;
update(1,1,n,x,str[0]);
}
}
}
return 0;
}
E HDU - 3006
https://cn.vjudge.net/problem/17879/origin
给一些n个集合 数字只有从1~m
求集合合并能组合多少种不同的集合
注意到m很小 所以直接枚举集合
然后看能不能组成
check的时候把没有集合不需要的数往里加就行了
复杂度m * n * 2^m
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <queue>
#include <cstdio>
#include <map>
#include <set>
#include <utility>
#include <stack>
#include <cstring>
#include <cmath>
#include <vector>
#include <ctime>
#include <bitset>
#include <assert.h>
using namespace std;
#define pb push_back
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define ansn() printf("%d\n",ans)
#define lansn() printf("%lld\n",ans)
#define r0(i,n) for(int i=0;i<(n);++i)
#define r1(i,e) for(int i=1;i<=e;++i)
#define rn(i,e) for(int i=e;i>=1;--i)
#define mst(abc,bca) memset(abc,bca,sizeof abc)
#define lowbit(a) (a&(-a))
#define all(a) a.begin(),a.end()
#define pii pair<int,int>
#define pll pair<long long,long long>
#define mp(aa,bb) make_pair(aa,bb)
#define lrt rt<<1
#define rrt rt<<1|1
#define X first
#define Y second
#define PI (acos(-1.0))
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
//const ll mod = 1000000007;
const ll mod = 1000000007;
const double eps=1e-12;
const int inf=0x3f3f3f3f;
//const ll infl = 100000000000000000;//1e17
const int maxn= 1e5+20;
const int maxm = 2e3+20;
//muv[i]=(p-(p/i))*muv[p%i]%p;
int in(int &ret) {
char c;
int sgn ;
if(c=getchar(),c==EOF)return -1;
while(c!='-'&&(c<'0'||c>'9'))c=getchar();
sgn = (c=='-')?-1:1;
ret = (c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9')ret = ret*10+(c-'0');
ret *=sgn;
return 1;
}
bitset<15>b[200];
int ans;
int n,m;
int counting;
bool need[20];
void check() {
++counting;
bitset<15>no;
bitset<15>y;
no.reset(),y.reset();
for(int i=1; i<=m; ++i)
if(!need[i])no.set(i);
else y.set(i);
if(y.count()==0)return ;
// for(int i=1; i<=n; ++i)if(y==b[i])return ;
bitset<15>bb;
bb.reset();
for(int i=1; i<=n; ++i) {
bitset<15>check = no&b[i];
if(check.count()>0)continue;
bb |= b[i];
if(bb==y)
{
++ans;
return ;
}
}
return ;
}
void dfs(int u) {
if(u==m+1) {
check();
return ;
}
r0(i,2) {
need[u] = i;
dfs(u+1);
}
}
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
while(~sdd(n,m)) {
ans = counting = 0;
for(int i=1; i<=n; ++i)b[i].reset();
for(int i=1; i<=n; ++i) {
int sz;
sd(sz);
r0(j,sz) {
int x;
sd(x);
b[i].set(x);
}
}
dfs(1);
ansn();
}
return 0;
}
F HDU - 3002
https://cn.vjudge.net/problem/27588/origin
无向图最小割 直接抄模版就行了
好像直接建边枚举一个固定点跟另一点作为源点汇点跑最大流也可以
可知对任意一点必定有一个点与其不在一个联通块
int g[111][111];
int v[111],w[111],c[111],S,T,now,n,m,x,y,z;
void se() {
int i,j,k,t;
for(i =0; i<n; ++i)v[i] = w[i] = 0;
for(S=T=-1,i =0; i<n; ++i) {
for(k=-inf,j =0; j<n; ++j)if(!c[j]&&!v[j]&&w[j]>k)k = w[t=j];
if(T==t)return;
S=T,T=t,now=k,v[t] = 1;
for(j=0; j<n; ++j)if(!c[j]&&!v[j])w[j]+=g[t][j];
}
}
int sw() {
int i,j,ans=inf;
for(i=0; i<n; ++i)c[i] = 0;
for(i=0; i<n-1; ++i) {
se();
if(now<ans)ans = now;
if(ans==0)return 0;
for(c[T]=1,j =0; j<n; ++j)if(!c[j])g[S][j]+=g[T][j],g[j][S]+=g[j][T];
}
return ans;
}
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
// int n,m;
while(~sdd(n,m)) {
mst(g,0);
S=T=now = x=y=z=0;
while(m--) {
sddd(x,y,z);
g[x][y] += z;
g[y][x] += z;
}
int ans = sw();
ansn();
}
return 0;
}
G HDU - 4607
https://cn.vjudge.net/problem/45587/origin
找出一个点使得能到k个点的步数最少
如果走到叶子节点并且还没走够那就还要走回来
所以要尽量减少来回走的点数
那么就需要使得最后不用重复走的尽量长
这就是树的直径的长度x
k > x时先重复走比x多出来的 最后再走x
< =x时直接走直径
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <queue>
#include <cstdio>
#include <map>
#include <set>
#include <utility>
#include <stack>
#include <cstring>
#include <cmath>
#include <vector>
#include <ctime>
#include <bitset>
#include <assert.h>
using namespace std;
#define pb push_back
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define ansn() printf("%d\n",ans)
#define lansn() printf("%lld\n",ans)
#define r0(i,n) for(int i=0;i<(n);++i)
#define r1(i,e) for(int i=1;i<=e;++i)
#define rn(i,e) for(int i=e;i>=1;--i)
#define mst(abc,bca) memset(abc,bca,sizeof abc)
#define lowbit(a) (a&(-a))
#define all(a) a.begin(),a.end()
#define pii pair<int,int>
#define pll pair<long long,long long>
#define mp(aa,bb) make_pair(aa,bb)
#define lrt rt<<1
#define rrt rt<<1|1
#define X first
#define Y second
#define PI (acos(-1.0))
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
//const ll mod = 1000000007;
const ll mod = 1000000007;
const double eps=1e-12;
const int inf=0x3f3f3f3f;
//const ll infl = 100000000000000000;//1e17
const int maxn= 1e5+20;
const int maxm = 2e3+20;
//muv[i]=(p-(p/i))*muv[p%i]%p;
int in(int &ret) {
char c;
int sgn ;
if(c=getchar(),c==EOF)return -1;
while(c!='-'&&(c<'0'||c>'9'))c=getchar();
sgn = (c=='-')?-1:1;
ret = (c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9')ret = ret*10+(c-'0');
ret *=sgn;
return 1;
}
int dis[maxn];
vector<int>g[maxn];
int n;
int dij(int s) {
mst(dis,0x3f);
dis[s] = 0;
priority_queue<pii>q;
q.push(mp(-0,s));
while(!q.empty()) {
pii p = q.top();
q.pop();
int u = p.Y;
int sz = g[u].size();
for(int j=0; j<sz; ++j) {
int v = g[u][j];
if(dis[v]>dis[u] + 1) {
dis[v] = dis[u]+1;
q.push(mp(-dis[v],v));
}
}
}
int mx = 0;
int id = 0;
for(int i=1; i<=n; ++i)if(dis[i]!=inf&&dis[i]>mx)mx = dis[i],id = i;
return id;
}
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
int T;
in(T);
r1(i,T) {
// printf("Case #%d: ",i);
int m;
sdd(n,m);
r1(i,n)g[i].clear();
r0(i,n-1){
int u,v;
sdd(u,v);
g[u].pb(v);
g[v].pb(u);
}
int rt = dij(1);
int ed = dij(rt);
int len = dis[ed];
while(m--)
{
int x;
sd(x);
int ro = x-1;
int ans ;
if(ro>len)ans = 2*(ro-len) + len;
else ans = ro;
ansn();
}
}
return 0;
}
H 51Nod - 1133
https://cn.vjudge.net/problem/27588/origin
X轴上有N条线段,每条线段有1个起点S和终点E。最多能够选出多少条互不重叠的线段。(注:起点或终点重叠,不算重叠)。
例如:151523233636,可以选23233636,这2条线段互不重叠。
离散之后在bit上dp
直接贪心也可以
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <queue>
#include <cstdio>
#include <map>
#include <set>
#include <utility>
#include <stack>
#include <cstring>
#include <cmath>
#include <vector>
#include <ctime>
#include <bitset>
#include <assert.h>
using namespace std;
#define pb push_back
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define ss(str) scanf("%s",str)
#define ansn() printf("%d\n",ans)
#define lansn() printf("%lld\n",ans)
#define r0(i,n) for(int i=0;i<(n);++i)
#define r1(i,e) for(int i=1;i<=e;++i)
#define rn(i,e) for(int i=e;i>=1;--i)
#define mst(abc,bca) memset(abc,bca,sizeof abc)
#define lowbit(a) (a&(-a))
#define all(a) a.begin(),a.end()
#define pii pair<int,int>
#define pll pair<long long,long long>
#define mp(aa,bb) make_pair(aa,bb)
#define lrt rt<<1
#define rrt rt<<1|1
#define X first
#define Y second
#define PI (acos(-1.0))
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
//const ll mod = 1000000007;
const ll mod = 1000000007;
const double eps=1e-12;
const int inf=0x3f3f3f3f;
//const ll infl = 100000000000000000;//1e17
const int maxn= 1e5+20;
const int maxm = 2e3+20;
//muv[i]=(p-(p/i))*muv[p%i]%p;
int in(int &ret) {
char c;
int sgn ;
if(c=getchar(),c==EOF)return -1;
while(c!='-'&&(c<'0'||c>'9'))c=getchar();
sgn = (c=='-')?-1:1;
ret = (c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9')ret = ret*10+(c-'0');
ret *=sgn;
return 1;
}
vector<int>v;
int id(int x)
{
return lower_bound(all(v),x) - v.begin() + 1;
}
struct node {
int l,r;
bool operator <( const node &o)const {
if(l!=o.l)return l<o.l;
return r<o.r;
}
} no[maxn];
int bit[maxn];
void update(int x,int v) {
while(x<maxn)bit[x]=max(bit[x],v),x+=lowbit(x);
}
int query(int x) {
int res =0 ;
while(x) {
res = max(res,bit[x]);
x-=lowbit(x);
}
return res;
}
int main() {
#ifdef LOCAL
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif // LOCAL
int n;
sd(n);
r1(i,n)sdd(no[i].l,no[i].r),v.pb(no[i].l),v.pb(no[i].r);
sort(all(v));
v.erase(unique(all(v)),v.end());
r1(i,n)no[i].l = id(no[i].l),no[i].r = id(no[i].r);
sort(no+1,no+1+n);
int ans = 1;
for(int i=1;i<=n;++i)
{
int l = no[i].l;
int r = no[i].r;
int check = query(l);
ans = max(ans,check+1);
update(r,check+1);
}
ansn();
return 0;
}