2
10
2016
10
2016
[BZOJ1875][SDOI2009]HH去散步[矩阵乘法]
看起来像个裸矩乘。。
但是题目中有这样一句话:
但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。
以点作为状态的算法很难处理这个条件,我们考虑以边作为状态。
只要在建矩阵的时候判断一下,不要从一条边直接走到它的反向边就可以了。
#include <iostream>
#include <cstring>
#include <cassert>
using namespace std;
typedef long long ll;
const int mod=45989;
struct matrix{
int r,c;
ll a[121][121];
matrix(int r,int c){
this->r=r;
this->c=c;
memset(a,0,sizeof(a));
}
ll * operator[](int p){
return a[p];
}
matrix operator =(const matrix& rhs){
//puts("WTF");
assert(r==rhs.r && c==rhs.c);
memcpy(a,rhs.a,sizeof(a));
return *this;
}
matrix operator *(matrix& rhs){
assert(c==rhs.r);
//puts("WTF");
matrix res(r,rhs.c);
//puts("WTF");
for(int i=0;i<r;i++)
for(int j=0;j<rhs.c;j++)
for(int k=0;k<c;k++)
(res[i][j]+=((a[i][k]*rhs[k][j])%mod))%=mod;
//puts("WTF");
return res;
}
matrix operator *=(matrix& rhs){
return *this=(*this)*rhs;
}
};
matrix power(const matrix& mat,ll b){
//puts("WTF");
matrix ret(mat.r,mat.c);
matrix t(mat.r,mat.c);
t=mat;
//puts("line 48");
for(int i=0;i<mat.r;i++)
ret[i][i]=1;
while(b){
//puts("WTF");
if (b%2)
ret=ret*t;
t=t*t;
b/=2;
}
return ret;
}
struct edge{
int from,to;
};
edge e[121];
int main(){
int n,m,t,a,b;
cin >> n >> m >> t >> a >> b;
a++,b++;
int cur=0;
for(int i=1;i<=m;i++){
int x,y;
cin >> x >> y;
x++,y++;
e[cur++]=(edge){x,y};
e[cur++]=(edge){y,x};
}
matrix mt(cur,cur);
for(int i=0;i<cur;i++){
for(int j=0;j<cur;j++){
if (e[i].to==e[j].from && i!=(j^1))
mt[i][j]++;
}
}
mt=power(mt,t-1);
int ans=0;
for(int i=0;i<cur;i++)
for(int j=0;j<cur;j++)
if (e[i].from==a && e[j].to==b)
(ans+=mt[i][j])%=mod;
cout << ans;
}
9
7
2015
7
2015
[NOIP2014TGDay1T3]飞扬的小鸟(刷表法dp)
三天写了一道NOIP题。。
题目在这里:http://uoj.ac/problem/17
暴力dp的方程是显然的:对于每一个i,j,更新dp[i+1][j-y[i]],dp[i+1][min(j+x[i]*k,m)](1<=k<=m)
然后发现min的部分是可以递推的。。
然后用dp[i][j][0]表示可以下降不能高度不变,dp[i][j][1]表示可以高度不变不能下降。。
转移看代码吧。。
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXSIZE=10000020;
int bufpos;
char buf[MAXSIZE];
void init(){
buf[fread(buf,1,MAXSIZE,stdin)]='\0';
bufpos=0;
}
int readint(){
bool isneg;
int val=0;
for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++);
bufpos+=(isneg=(buf[bufpos]=='-'))?1:0;
for(;isdigit(buf[bufpos]);bufpos++)
val=val*10+buf[bufpos]-'0';
return isneg?-val:val;
}
int dp[10001][1001][2];
int l[10001],h[10001],x[10001],y[10001];
int main(){
init();
int n=readint(),m=readint(),k=readint();
for(int i=0;i<n;i++){
x[i]=readint(),y[i]=readint();
}
fill(l,l+n+1,0);
fill(h,h+n+1,m+1);
for(int i=1;i<=k;i++){
int p=readint();
l[p]=readint();
h[p]=readint();
}
memset(dp,0x3f,sizeof(dp));
memset(dp[0],0,sizeof(dp[0]));
for(int j=0;j<=m;j++)
dp[0][j][1]=INF;
int maxr=0;
for(int i=0;i<n;i++)
for(int j=0;j<=m;j++){
if (j<=l[i] || j>=h[i]){
dp[i][j][0]=INF;
//printf("dp[%d][%d][1] is %d\n",i,j,dp[i][j][1]);
//printf("dp[%d][%d][0] is %d\n",i,j,dp[i][j][0]);
}
dp[i+1][min(j+x[i],m)][0]=min(dp[i+1][min(j+x[i],m)][0],dp[i][j][0]+1);
if (j>y[i])
dp[i+1][j-y[i]][0]=min(dp[i+1][j-y[i]][0],dp[i][j][0]);
dp[i+1][j][0]=min(dp[i+1][j][0],dp[i][j][1]);
dp[i][min(j+x[i],m)][1]=min(dp[i][min(j+x[i],m)][1],dp[i][j][1]+1);
dp[i][min(j+x[i],m)][1]=min(dp[i][min(j+x[i],m)][1],dp[i][j][0]+1);
if (dp[i][j][0]<INF){
maxr=i;
}
//printf("dp[%d][%d][1] is %d\n",i,j,dp[i][j][1]);
//printf("dp[%d][%d][0] is %d\n",i,j,dp[i][j][0]);
}
int ans=INF;
for(int i=0;i<=m;i++)
ans=min(ans,dp[n][i][0]);
if (ans>=INF){
printf("0\n");
int cnt=0;
for(int i=0;i<=maxr;i++)
if (h[i]<m+1)
cnt++;
printf("%d\n",cnt);
}
else printf("1\n%d\n",ans);
}
9
4
2015
4
2015
Templates
一些奇怪的模板
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXSIZE=30000020;
int bufpos;
char buf[MAXSIZE];
void init(){
buf[fread(buf,1,MAXSIZE,stdin)]='\0';
bufpos=0;
}
int readint(){
bool isneg;
int val=0;
for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++);
bufpos+=(isneg=(buf[bufpos]=='-'))?1:0;
for(;isdigit(buf[bufpos]);bufpos++)
val=val*10+buf[bufpos]-'0';
return isneg?-val:val;
}
char readchar(){
for(;isspace(buf[bufpos]);bufpos++);
return buf[bufpos++];
}
struct segtree{
ll minv[maxn*8];
int n,p;
ll v;
segtree(){
memset(minv,0,sizeof(minv));
}
void _update_(int o,int l,int r){
if (l==r){
minv[o]=v;
assert(l==p);
return;
}
ll m=l+(r-l)/2;
//puts("line 35");
if (p<=m)
_update_(o*2,l,m);
else _update_(o*2+1,m+1,r);
minv[o]=min(minv[o*2],minv[o*2+1]);
}
void update(int p,ll v){
this->p=p;
this->v=v;
_update_(1,1,n);
//puts("updated once");
}
int ql,qr;
ll _query_(int o,int l,int r){
if (ql<=l && r<=qr)
return minv[o];
ll ans=INF;
int m=l+(r-l)/2;
if (ql<=m)
ans=min(ans,_query_(o*2,l,m));
if (qr>=m+1)
ans=min(ans,_query_(o*2+1,m+1,r));
return ans;
}
ll query(int l,int r){
if (l>r)
return INF;
ql=l;
qr=r;
return _query_(1,1,n);
}
};
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct acatm{
int ch[201][26];
int val[201];
int f[201];
int last[201];
bool match[1000001][21];
int sz,cnt;
acatm(){
sz=1;
cnt=0;
memset(ch[0],0,sizeof(ch[0]));
memset(val,0,sizeof(val));
}
inline int idx(char c){
return c-'a';
}
void ins(char* s){
int len=strlen(s),u=0;
for(int i=0;i<len;i++){
int c=idx(s[i]);
int v=ch[u][c];
if (!v){
ch[u][c]=v=sz++;
memset(ch[v],0,sizeof(ch[v]));
val[v]=0;
}
u=v;
}
val[u]=++cnt;
}
void getfail(){
queue<int> q;
f[0]=0;
last[0]=0;
for(int i=0;i<26;i++){
int u=ch[0][i];
if (u){
q.push(u);
f[u]=0;
last[u]=0;
}
}
while(!q.empty()){
int r=q.front();q.pop();
for(int i=0;i<26;i++){
int u=ch[r][i];
if (!u){
ch[r][i]=ch[f[r]][i];
continue;
}
int v=f[r];
while(v && !ch[v][i])
v=f[v];
f[u]=ch[v][i];
//printf("f[%d]=%d\n",u,f[u]);
last[u]=val[f[u]]?f[u]:last[f[u]];
q.push(u);
}
}
}
void print(int i,int u){
if (u){
match[i][val[u]]=true;
print(i,last[u]);
}
}
void fi(char* s){
memset(match,0,sizeof(match));
int len=strlen(s),u=0;
for(int i=0;i<len;i++){
int c=idx(s[i]);
u=ch[u][c];
//printf("i=%d,u=%d\n",i,u);
if (val[u])
print(i,u);
else if (last[u]) print(i,last[u]);
}
}
};
struct edge{
int from,to,next;
};
struct graph{
int n,m;
edge e[400001];
bool iscut[100001];
bool isbri[400001];
int low[100001];
int pre[100001];
int first[100001];
int cnt;
graph(){
m=0;
cnt=0;
memset(first,-1,sizeof(first));
memset(pre,0,sizeof(pre));
memset(iscut,0,sizeof(iscut));
memset(isbri,0,sizeof(isbri));
}
void addedge(int from,int to){
e[++m]=(edge){from,to,first[from]};
first[from]=m;
}
int dfs(int u,int fa){
int& lowu=low[u];
lowu=pre[u]=++cnt;
int child=0;
for(int i=first[u];i!=-1;i=e[i].next){
int v=e[i].to;
if (!pre[v]){
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if (lowv>=pre[u])
iscut[u]=true;
if (lowv>pre[u])
isbri[i]=true; //Only one of (u,v) and (v,u) will be labeled,be careful!
}
else if (pre[v]<pre[u] && v!=fa)
lowu=min(lowu,pre[v]);
}
if (fa<0 && child==1)
iscut[u]=false;
return lowu;
}
};
struct edge{
int from,to,next;
};
struct graph{
int n,m;
edge e[100001];
int first[10001];
int lowlink[10001];
int sccno[10001];
int pre[10001];
int num[10001];
int out0[10001];
int cnt,dfsc;
stack<int> s;
graph(){
m=0;
memset(first,-1,sizeof(first));
}
void addedge(int from,int to){
e[++m]=(edge){from,to,first[from]};
first[from]=m;
}
void dfs(int u){
pre[u]=lowlink[u]=++dfsc;
s.push(u);
for(int i=first[u];i!=-1;i=e[i].next){
int v=e[i].to;
if (!pre[v]){
dfs(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
} else if (!sccno[v]){
lowlink[u]=min(lowlink[u],pre[v]);
}
}
if (lowlink[u]==pre[u]){
cnt++;
for(;;){
int x=s.top();
s.pop();
sccno[x]=cnt;
num[cnt]++;
if (x==u)
break;
}
}
}
void getscc(){
dfsc=cnt=0;
memset(pre,0,sizeof(pre));
memset(sccno,0,sizeof(sccno));
memset(num,0,sizeof(num));
for(int i=1;i<=n;i++)
if (!pre[i])
dfs(i);
}
void rebuild(){
memset(out0,1,sizeof(out0));
for(int i=1;i<=n;i++){
for(int j=first[i];j!=-1;j=e[j].next)
if (sccno[i]!=sccno[e[j].to])
out0[sccno[i]]=false;
}
}
};
#include <cstdio>
#include <cstring>
using namespace std;
struct edge{
int from,to,next;
};
struct twosat{
int n,m;
edge e[2001];
bool mark[201];
int first[201];
int s[201],c;
inline int other(int x){
return x%2?x+1:x-1;
}
twosat(){
m=0;
memset(mark,0,sizeof(mark));
memset(first,-1,sizeof(first));
}
void clear(){
m=0;
memset(mark,0,sizeof(mark));
memset(first,-1,sizeof(first));
}
void addedge(int from,int to){
e[++m]=(edge){from,to,first[from]};
first[from]=m;
}
void addclue(int x,int xval,int y,int yval){
x=x*2+xval-1;
y=y*2+yval-1;
addedge(other(x),y);
addedge(other(y),x);
}
bool dfs(int x){
if (mark[x])
return true;
if (mark[other(x)])
return false;
mark[x]=true;
s[++c]=x;
for(int i=first[x];i!=-1;i=e[i].next){
if (!dfs(e[i].to))
return false;
}
return true;
}
bool solve(){
/*for(int i=1;i<=2*n;i++){
printf("edges from %d:",i);
for(int j=first[i];j!=-1;j=e[j].next)
printf("%d ",e[j].to);
putchar('\n');
}*/
for(int i=1;i<=2*n;i+=2){
if (!mark[i] && !mark[i+1]){
c=0;
if (!dfs(i)){
for(int j=1;j<=c;j++)
mark[s[j]]=false;
c=0;
if (!dfs(i+1))
return false;
}
}
}
return true;
}
};
typedef long long ll;
struct edge{
int from,to;
int dist;
int next;
};
struct graph{
int n,m;
ll d[1002];
edge e[200001];
int first[1002];
bool inq[1002];
int cnt[1002];
int q[2000002];
void init(int n){
this->n=n;
memset(first,-1,sizeof(int)*1002);
m=0;
}
void addedge(int from,int to,int dist){
e[++m]=(edge){from,to,dist,first[from]};
first[from]=m;
}
bool spfa(int s){
//int q[100004];
int f=1,r=1;
memset(d,0x3f,sizeof(ll)*1002);
memset(inq,0,sizeof(int)*1002);
memset(cnt,0,sizeof(int)*1002);
d[s]=0;
q[r]=s;
r++;
inq[s]=true;
cnt[s]=1;
while (f<r){
register int u=q[f];
f++;
inq[u]=false;
register int i=first[u];
while(i!=-1){
register ll t=d[u]+e[i].dist;
register int v=e[i].to;
if(d[u]<INF && d[v]>t){
d[v]=t;
if (!inq[v]){
q[r]=v;
r++;
inq[v]=true;
if (++cnt[v]>n){
return false;
}
}
}
i=e[i].next;
}
}
return true;
}
};
typedef long long ll;
struct edge{
ll from,to,dist,next;
};
struct heapnode{
ll d,u;
bool operator < (const heapnode& rhs) const{
return d>rhs.d;
}
};
struct graph{
ll n,m;
edge* e=new edge[200003];
ll* first=new ll[200003];
ll* d=new ll[200003];
ll* p=new ll[200003];
bool* done=new bool[200003];
void init(ll n){
this->n=n;
m=0;
memset(first,-1,200003*sizeof(ll));
}
void addedge(ll from,ll to,ll dist){
e[++m]=(edge){from,to,dist,first[from]};
first[from]=m;
}
void dijkstra(ll s){
priority_queue<heapnode> q;
memset(d,0x3f,200003*sizeof(ll));
d[s]=0;
memset(done,0,200003*sizeof(bool));
memset(p,0,200003*sizeof(ll));
q.push((heapnode){0,s});
while(!q.empty()){
ll u=q.top().u;
q.pop();
if (done[u])
continue;
done[u]=true;
//prllf("u=%d\n",u);
ll i=first[u];
while (i!=-1){
if (d[u]+e[i].dist<d[e[i].to]){
d[e[i].to]=d[u]+e[i].dist;
p[e[i].to]=u;
q.push((heapnode){d[e[i].to],e[i].to});
}
i=e[i].next;
}
}
}
};
typedef int ll;
int mod;
struct matrix{
int r,c;
ll a[51][51];
matrix(int r,int c){
this->r=r;
this->c=c;
memset(a,0,sizeof(a));
}
ll * operator[](int p){
return a[p];
}
matrix operator =(const matrix& rhs){
//puts("WTF");
assert(r==rhs.r && c==rhs.c);
memcpy(a,rhs.a,sizeof(a));
return *this;
}
matrix operator *(matrix& rhs){
assert(c==rhs.r);
//puts("WTF");
matrix res(r,rhs.c);
//puts("WTF");
for(int i=1;i<=r;i++)
for(int j=1;j<=rhs.c;j++)
for(int k=1;k<=c;k++)
(res[i][j]+=((a[i][k]*rhs[k][j])%mod))%=mod;
//puts("WTF");
return res;
}
matrix operator *=(matrix& rhs){
return *this=(*this)*rhs;
}
};
matrix power(const matrix& mat,ll b){
//puts("WTF");
matrix ret(mat.r,mat.c);
matrix t(mat.r,mat.c);
t=mat;
//puts("line 48");
for(int i=1;i<=mat.r;i++)
ret[i][i]=1;
while(b){
//puts("WTF");
if (b%2)
ret=ret*t;
t=t*t;
b/=2;
}
return ret;
}
struct edge{
int from,to,next;
};
struct graph{
int nl,m;
edge e[maxm];
int first[maxn];
int match[maxn];
bool vis[maxn];
void init(int nl){
this->nl=nl;
m=0;
memset(first,-1,sizeof(first));
}
void addedge(int from,int to){
e[++m]=(edge){from,to,first[from]};
first[from]=m;
}
bool dfs(int u){
for(int i=first[u];i!=-1;i=e[i].next){
int v=e[i].to;
if (!vis[v]){
vis[v]=true;
if (match[v]==-1 || dfs(match[v])){
match[u]=v;
match[v]=u;
return true;
}
}
}
return false;
}
int work(){
int ans=0;
memset(match,-1,sizeof(match));
for(int i=1;i<=nl;i++)
if (match[i]==-1){
memset(vis,0,sizeof(vis));
if (dfs(i))
++ans;
}
return ans;
}
};
struct bit{
int t[32003];
int n;
bit(){
memset(t,0,sizeof(t));
}
inline int lowbit(int x){
return (x&(-x));
}
int sum(int x){
int ret=0;
for(int i=x;i>0;i-=lowbit(i))
ret+=t[i];
return ret;
}
void add(int p,int v){
for(int i=p;i<=n;i+=lowbit(i))
t[i]+=v;
/*for(int i=1;i<=n;i++)
printf("%d ",t[i]);*/
}
};