# Noip2017赛前的一些记录

## 数据结构--强连通分量

### 城市轰炸【JZOJ5452】

#### 分析

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#define LL long long

using namespace std;

inline char nc(){
/*
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
*/return getchar();
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

{
char c=nc();int len=1;
for(;!(c>='a' && c<='z');c=nc()) if (c==EOF) return 0;
for(;(c>='a' && c<='z');s[len++]=c,c=nc());
s[len++]='\0';
return len-2;
}

for (x=nc();!(x>='A' && x<='Z');x=nc());
}

int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}

struct Edge
{
int to,nxt;
}edge[1000010];

int h[1000010],vis[1000010],sta[1000010],sccc[1000010];
int dfn[1000010],f[1000010];
int ep,cnt,scc,t,n,m;
vector<int> a[1000010];

{
edge[ep].to=cv;
edge[ep].nxt=h[cu];
h[cu]=ep++;
}

void Tarjan(int u)
{
int v;
dfn[u]=f[u]=++cnt;
vis[u]=1;
sta[t++]=u;
for (int i=h[u];i!=-1;i=edge[i].nxt)
{
v=edge[i].to;
if (!dfn[v])
{
Tarjan(v);
f[u]=min(f[u],f[v]);
}
else if (vis[v]) f[u]=min(f[u],dfn[v]);
}
if (dfn[u]==f[u])
{
++scc;
do
{
v=sta[--t];
vis[v]=0;
sccc[v]=scc;
}while (u!=v);
}
}

int main()
{
int x,y;
memset(h,-1,sizeof(h));
for (int i=1;i<=m;i++)
memset(dfn,0,sizeof(dfn));
memset(vis,0,sizeof(vis));
scc=t=cnt=0;
int u,v;
for (u=1;u<=n;u++)
if (!dfn[u]) Tarjan(u);
/*for (int i=1;i<=n;i++)
print(sccc[i]),putchar(' ');
puts("");print(scc);puts("");*/
memset(vis,0,sizeof(vis));
memset(dfn,0,sizeof(dfn));
for (int u=1;u<=n;u++)
{
dfn[sccc[u]]++;
for (int i=h[u];i!=-1;i=edge[i].nxt)
if (sccc[u]!=sccc[edge[i].to])
a[sccc[u]].push_back(sccc[edge[i].to]),vis[sccc[edge[i].to]]++;
}
queue<int> q;
memset(f,0,sizeof(f));
for (int i=1;i<=scc;i++)
if (vis[i]==0) q.push(i),f[i]=dfn[i];
while (!q.empty())
{
x=q.front();q.pop();
for (int i=0;i<a[x].size();i++)
{
vis[a[x][i]]--;
if (vis[a[x][i]]==0) q.push(a[x][i]);
f[a[x][i]]=max(f[a[x][i]],f[x]+dfn[a[x][i]]);
}
}
int ans=0;
for (int i=1;i<=scc;i++)
ans=max(ans,f[i]);
print(ans),puts("");
return 0;
}

## 数据结构--树状数组

### 斯诺(snow)

#### 题目描述

“谨向英勇的中国致敬” 埃德加·斯诺到达陕甘宁边区后,决定出个 NOIP(NOI Professional)题,向西方世界介绍他所看到的事情. 斯诺在调查中发现,Mao Zedong 先生非常喜欢序列和区间,于是斯诺给了 Mao Zedong 先生一个长度 为 n 的,每个元素都是 0,1,2 的序列. Mao Zedong 发现这个序列中一共有$n(n+1)/2$个区间,这太多了.运用辩证法,他认为,对于一个区间,只 有其中任意一种数字的数目都不超过区间的一半时,这个区间才算是革命的.现在 Mao Zedong 先生建议 斯诺数一数这个序列里有多少个革命的区间. 例如,对于序列 010102201,区间”201”是合法的,里面每种数字只占三分之一.区间”2”是不革命的,2 占 据了这个区间的 100%.(由此可以看出,长度为 1 的区间一定不合法).区间”0101”和“10”是合法的,0 和 1 各 占据了区间的一半,但是没有超过一半.

#### 分析

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define LL long long

using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

{
char c=nc();int len=1;
for(;!(c>='0' && c<='2');c=nc()) if (c==EOF) return 0;
for(;(c>='0' && c<='2');s[len++]=c,c=nc());
s[len++]='\0';
return len-2;
}

for (x=nc();!(x>='A' && x<='Z');x=nc());
}

int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}

int n,m;
char ch[5000010];
int f1[5000010],f2[5000010],f0[5000010];
LL f[10000010],c[10000010];

bool check()
{
for (int i=1;i<=n;i++)
if (ch[i]=='2') return false;
return true;
}

void change(int x,LL y)
{
for (;x<=2*n+1;x+=x&(-x)) c[x]+=y;
}

LL query(int x)
{
LL res=0;
for (;x;x-=x&(-x)) res+=c[x];
return res;
}

LL solve()
{
LL res=0;
memset(c,0,sizeof(c));
for (int i=0;i<=n;i++)
res+=query(2*n)-query(f1[i]),
change(f1[i],1);
return res;
}

LL Solve()
{
LL res=0,s=0;
memset(c,0,sizeof(c));
for (int i=0;i<=n;i++)
{
res+=i-s,c[f1[i]]++;
s++;
if (f1[i+1]>f1[i]) s+=c[f1[i+1]];else s-=c[f1[i]];
}
return res;
}

int main()
{
freopen("snow.in","r",stdin);
freopen("snow.out","w",stdout);
if (n<=3000)
{
f1[0]=0;f2[0]=0;f0[0]=0;
for (int i=1;i<=n;i++)
{
f0[i]=f0[i-1],f1[i]=f1[i-1],f2[i]=f2[i-1];
if (ch[i]=='0') f0[i]++;
if (ch[i]=='1') f1[i]++;
if (ch[i]=='2') f2[i]++;
}
int ans=0;
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++)
if (f0[j]-f0[i-1]<=(j-i+1)/2&&f1[j]-f1[i-1]<=(j-i+1)/2&&f2[j]-f2[i-1]<=(j-i+1)/2) ans++;
print(ans),puts("");
}
else if (check())
{
f0[0]=0;
memset(f,0,sizeof(f));f[n]=1;
for (int i=1;i<=n;i++)
{
if (ch[i]=='0') f0[i]=f0[i-1]+1;else f0[i]=f0[i-1]-1;
f[f0[i]+n]++;
}
LL ans=0LL;
for (int i=0;i<=n+n;i++)
ans+=f[i]*(f[i]-1LL)/2LL;
print(ans),puts("");
}
else if (n<=100000)
{
for (int i=1;i<=n;i++)
if (ch[i]=='0') f0[i]=-1;else f0[i]=1;
f1[0]=0;
for (int i=1;i<=n;i++)
f1[i]=f1[i-1]+f0[i];
for (int i=0;i<=n;i++)
f1[i]+=n+1;
LL ans=((LL)n)*((LL)(n+1))/2LL;
ans-=solve();
for (int i=1;i<=n;i++)
if (ch[i]=='1') f0[i]=-1;else f0[i]=1;
f1[0]=0;
for (int i=1;i<=n;i++)
f1[i]=f1[i-1]+f0[i];
for (int i=0;i<=n;i++)
f1[i]+=n+1;
ans-=solve();
for (int i=1;i<=n;i++)
if (ch[i]=='2') f0[i]=-1;else f0[i]=1;
f1[0]=0;
for (int i=1;i<=n;i++)
f1[i]=f1[i-1]+f0[i];
for (int i=0;i<=n;i++)
f1[i]+=n+1;
ans-=solve();
print(ans),puts("");
}
else
{
for (int i=1;i<=n;i++)
if (ch[i]=='0') f0[i]=-1;else f0[i]=1;
f1[0]=0;
for (int i=1;i<=n;i++)
f1[i]=f1[i-1]+f0[i];
for (int i=0;i<=n;i++)
f1[i]+=n+1;
LL ans=((LL)n)*((LL)(n+1))/2LL;
ans-=Solve();
for (int i=1;i<=n;i++)
if (ch[i]=='1') f0[i]=-1;else f0[i]=1;
f1[0]=0;
for (int i=1;i<=n;i++)
f1[i]=f1[i-1]+f0[i];
for (int i=0;i<=n;i++)
f1[i]+=n+1;
ans-=Solve();
for (int i=1;i<=n;i++)
if (ch[i]=='2') f0[i]=-1;else f0[i]=1;
f1[0]=0;
for (int i=1;i<=n;i++)
f1[i]=f1[i-1]+f0[i];
for (int i=0;i<=n;i++)
f1[i]+=n+1;
ans-=Solve();
print(ans),puts("");
}
return 0;
}

## 图论--K短路

### 牛跑步【Usaco2008Mar】

#### 题目描述

Bessie has taken heed of the evils of sloth and has decided to get fit by jogging from the barn to the pond several times a week. She doesn't want to work too hard, of course, so she only plans to jog downhill to the pond and then amble back to the barn at her leisure.

Bessie also doesn't want to jog any too far either, so she generally takes the shortest sequence of cow paths to get to the pond. Each of the M (1 <= M <= 10,000) cow paths connects two pastures

conveniently numbered 1..N (1 <= N <= 1000). Even more conveniently, the pastures are numbered such that if X>Y then the cow path from pasture X to pasture Y runs downhill. Pasture N is the barn (at the top of the hill) and pasture 1 is the pond (at the bottom).

Just a week into her regimen, Bessie has begun to tire of always taking the same route to get to the pond. She would like to vary her route by taking different cow paths on different days. Specifically, Bessie would like to take exactly K (1 <= K <= 100) different routes for variety. To avoid too much exertion, she wants these to be the K shortest routes from the barn to the pond. Two routes are considered different if they comprise different sequences of cow paths.

Help Bessie determine how strenuous her workout will be by determining the lengths of each of the K shortest routes on the network of pastures. You will be supplied a list of downhill cow paths from X_i to Y_i along with the cow path's length: (X_i, Y_i, D_i) where (1 <= Y_i < X_i; Y_i < X_i <= N). Cowpath i has length D_i (1 <= D_i <= 1,000,000).

#### 输入格式

Line 1: Three space-separated integers: N, M, and K

Lines 2..M+1: Line i+1 describes a downhill cow path using three space-separated integers: X_i, Y_i, and D_i

#### 输出格式

Lines 1..K: Line i contains the length of the i-th shortest route or -1 if no such route exists. If a shortest route length occurs multiple times, be sure to list it multiple times in the output.

#### 分析

K短路的模板题，就当做复习，又写了一遍代码

1.A*算法

A*算法在人工智能中是一种典型的启发式搜索算法，启发中的估价是用估价函数表示的：$$h(n)=f(n)+g(n)$$

2 第K最短路的算法

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#define LL long long

using namespace std;

inline char nc(){
/*
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
*/return getchar();
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

{
char c=nc();int len=1;
for(;!(c>='a' && c<='z');c=nc()) if (c==EOF) return 0;
for(;(c>='a' && c<='z');s[len++]=c,c=nc());
s[len++]='\0';
return len-2;
}

for (x=nc();!(x>='A' && x<='Z');x=nc());
}

int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}
int n,m,k,s,t;
int tot,point[10010],nxt[10010],v[10010],_tot,_point[10010],_nxt[10010],_v[10010];LL c[10010],_c[10010];
LL dis[10010],ans[10010];bool vis[10010];int cnt[10010];
struct data
{
int x;LL g,h;
bool operator < (const data &a) const
{
return g+h>a.g+a.h;
}
};

{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
++_tot; _nxt[_tot]=_point[y]; _point[y]=_tot; _v[_tot]=x; _c[_tot]=z;
}
void spfa()
{
queue <int> q;
memset(dis,127,sizeof(dis));
dis[t]=0;vis[t]=1;q.push(t);
while (!q.empty())
{
int now=q.front();q.pop();
vis[now]=0;
for (int i=_point[now];i;i=_nxt[i])
if (dis[_v[i]]>dis[now]+_c[i])
{
dis[_v[i]]=dis[now]+_c[i];
if (!vis[_v[i]]) vis[_v[i]]=1,q.push(_v[i]);
}
}
}

void Astar()
{
priority_queue <data> q;
q.push((data){s,0,dis[s]});
int size=0;
while (!q.empty())
{
data now=q.top();q.pop();
++cnt[now.x];
if (cnt[now.x]>k) continue;
if (now.x==t) ans[++size]=now.g;
if (cnt[t]==k) return;
for (int i=point[now.x];i;i=nxt[i])
q.push((data){v[i],now.g+c[i],dis[v[i]]});
}
}

int main()
{
int x,y;LL z;
for (int i=1;i<=m;++i)
{
if (x<y) swap(x,y);
}
s=n,t=1;
spfa();
memset(ans,-1,sizeof(ans));
Astar();
for (int i=1;i<=k;++i)
print(ans[i]),puts("");
return 0;
}

## 图论--二分图匹配

### 超级英雄Hero【HNOI2006】

#### 分析

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define LL long long

using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}

int lk[1001];
int n,m;
bool y[1001];
vector<int> mp[1001];

bool find(int x)
{
for (int i=0;i<mp[x].size();i++)
{
if(!y[mp[x][i]])
{
y[mp[x][i]]=1;
if(!lk[mp[x][i]]||find(lk[mp[x][i]]))
{
lk[mp[x][i]]=x;
return 1;
}
}
}
return 0;
}

int main()
{
int u,v;
for(int i=1;i<=m;i++)
int ans=0;
for(int i=1;i<=m;i++)
{
memset(y,0,sizeof(y));
if(find(i)) ans++;
else break;
}
print(ans);puts("");
return 0;
}

## 动态规划

### 保镖排队

#### 题目描述

CZ一共雇佣了$N$个保镖（编号为$1$$N$）。每个保镖虽然身手敏捷武功高强，但是他在其余$N-1$个保镖里，都会有一个“上司”，他会对他的上司言听计从。但一号保镖例外，他武功盖世，不惧怕其余任何保镖，所以他没有上司。

CZ会对这 N 个保镖进行定期视察。每次视察的时候，首先会让所有保镖排队。 对于每个保镖，在他心目中会对他的所有下属的武功实力排个队。现在 CZ 要求排出来的队伍满足：

①互为上司-下属的两个保镖，上司在前，下属在后

②对于一个保镖的所有下属，武功实力较强的在前，较弱的在后。

CZ 想知道，总的排队方法数除以$10007$的余数是多少。

#### 分析

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define LL long long

using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

{
char c=nc();int len=1;
for(;!(c>='a' && c<='z');c=nc()) if (c==EOF) return 0;
for(;(c>='a' && c<='z');s[len++]=c,c=nc());
s[len++]='\0';
return len-2;
}

for (x=nc();!(x>='A' && x<='Z');x=nc());
}

int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}

int T,n,m;
LL fac[2010],ifac[2010];
const LL mo=10007;
const int N=2000;
vector<int> a[1010];
int f[1010],c[1010],ne[1010],cn[1010];

LL pow(LL x,LL y)
{
LL res=1;
for (;y;y>>=1)
{
if (y&1) res=res*x%mo;
x=x*x%mo;
}
return res;
}

LL C(int x,int y)
{
if (y==0 || x==y) return 1LL;
if (x<y) return 0LL;
return fac[x]*ifac[y]%mo*ifac[x-y]%mo;
}

void init()
{
fac[0]=1;
for (int i=1;i<=N;i++)
fac[i]=fac[i-1]*i%mo;
ifac[N]=pow(fac[N],mo-2);
for (int i=N-1;i>=1;i--)
ifac[i]=ifac[i+1]*(i+1)%mo;
}

void dfs(int x)
{
int s=0;
for (int i=0;i<a[x].size();i++)
{
if (i!=0) ne[a[x][i-1]]=a[x][i];
dfs(a[x][i]);
s+=c[a[x][i]];
}
c[x]=s+1;
for (int i=0;i<a[x].size();i++)
s-=c[a[x][i]],cn[a[x][i]]=s;
}

void solve(int x)
{
f[x]=1;
for (int i=a[x].size()-1;i>=0;i--)
{
solve(a[x][i]);
f[x]=f[x]*f[a[x][i]]%mo;
if (i!=a[x].size()-1) f[x]=f[x]*C(c[a[x][i]]-1+cn[a[x][i]],c[a[x][i]]-1)%mo;
}
}

int main()
{
while (T--)
{
int x,y;
memset(ne,0,sizeof(ne));
memset(f,0,sizeof(f));
memset(c,0,sizeof(c));
memset(cn,0,sizeof(cn));
for (int i=1;i<=n;i++)
{
a[i].clear();
}
dfs(1);
solve(1);
print(f[1]);puts("");
}
return 0;
}

## 数学

### 小球问题的万能图

(PS.我没记错的话，这张图片是cwy给我的...不过有个错误，我已经更正了QwQ)

### Biscuits(AtCoder Grand Contest 017)

#### 题目描述

There are N bags of biscuits. The i-th bag contains Ai biscuits.

Takaki will select some of these bags and eat all of the biscuits inside. Here, it is also possible to select all or none of the bags.

He would like to select bags so that the total number of biscuits inside is congruent to P modulo 2. How many such ways to select bags there are?

#### 输入格式

Input is given from Standard Input in the following format:

N P
A1 A2 ... AN

#### 输出格式

Print the number of ways to select bags so that the total number of biscuits inside is congruent to P modulo 2.

1≤N≤50
P=0 or 1
1≤Ai≤100

#### 分析

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#define LL long long

using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

int wt,ss[19];
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}

int n,m,b[4];

LL pow(LL x,int y)
{
LL res=1;
for (;y;y>>=1)
{
if (y&1) res*=x;
x*=x;
}
return res;
}

int main()
{
int x;
for (int i=1;i<=n;i++)
if (b[1]==0)
{
if (m==0) print(pow(2LL,b[0]));
else print(0);
}
else print(pow(2LL,b[0]+b[1])/2);
puts("");
return 0;
}

### Moderate Differences(AtCoder Grand Contest 017)

#### 题目描述

There are N squares in a row. The leftmost square contains the integer A, and the rightmost contains the integer B. The other squares are empty.

Aohashi would like to fill the empty squares with integers so that the following condition is satisfied:

For any two adjacent squares, the (absolute) difference of the two integers in those squares is between C and D (inclusive).
As long as the condition is satisfied, it is allowed to use arbitrarily large or small integers to fill the squares. Determine whether it is possible to fill the squares under the condition.

#### 输入格式

Input is given from Standard Input in the following format:

N A B C D

#### 输出格式

Print YES if it is possible to fill the squares under the condition; print NO otherwise.

#### 数据范围

3≤N≤500000
0≤A≤109
0≤B≤109
0≤C≤D≤109
All input values are integers.

#### 分析

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#define LL long long

using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

LL N,A,B,C,D,Min,Max;

bool check(LL x)
{
if (Min<=x&&Max>=x) return true;
for (LL i=1;i<=(N-1);i++)
{
Min=Min-C-D;Max=Max-C-D;
if (Min<=x&&Max>=x) return true;
}
return false;
}

int main()
{
LL x=B-A;Min=C*(N-1);Max=D*(N-1);
if (check(B-A)) puts("YES");else puts("NO");
return 0;
}

### 数列递推(LibreOJ NOIP Round #1 Day 1)

#### 题目描述

sosusosu虐爆OI之后成为了一名文化课选手。一天，他做作业碰到了一堆数列问题，每道题给出的数列都是以下形式：

sosusosu 研究了这些数列，发现它们十分优美充满人类智慧，于是决定出一道OI题。

sosusosu 给了你一个集合$S\subset \mathbb{N}$，他想问你对于$S$中的每个数$s_i$，使得$a_{s_i}$最大的$s_i$和使得$a_{s_i}$最小的$s_i$分别是多少。如果这样的$s_i$有多个，请你回答最小的一个。

#### 分析

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define LL long long

using namespace std;

inline char nc(){
///*
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
//*/return getchar();
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

{
char c=nc();int len=1;
for(;!(c>='0' && c<='9');c=nc()) if (c==EOF) return 0;
for(;(c>='0' && c<='9');s[len++]=c,c=nc());
s[len++]='\0';
return len-2;
}

for (x=nc();!(x>='A' && x<='Z');x=nc());
}

int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}

int n,m,a[300010];
LL f[100];

bool cmp(int x,int y)
{
return x<y;
}

int main()
{
//	freopen("pa.in","r",stdin);
//	freopen("pa.out","w",stdout);
int Max=0,Min=2000000000;
for (int i=1;i<=n;i++)
sort(a+1,a+1+n,cmp);
LL x,y,z;
while (m--)
{
if (x==0 && y==0) {print(a[1]),putchar(' '),print(a[1]),puts("");continue;}
memset(f,0,sizeof(f));
f[0]=x;f[1]=y;int i=2;
while (f[i-1]*f[i-2]<=0)
f[i]=z*f[i-1]+f[i-2],i++;
LL maxm,minm,maxw,minw;
if (f[i-1]<0)
{
i--;
while (f[i]>f[0]||f[i]>f[1])
i++,f[i]=z*f[i-1]+f[i-2];
maxm=f[a[1]],minm=f[a[1]],maxw=a[1],minw=a[1];
int j=2;a[n+1]=i+2;
while (a[j]<=i)
{
if (f[a[j]]>maxm) maxm=f[a[j]],maxw=a[j];
if (f[a[j]]<minm) minm=f[a[j]],minw=a[j];
j++;
}
if (a[n]>i) minw=a[n];
}
else
{
i--;
while (f[i]<f[0]||f[i]<f[1])
i++,f[i]=z*f[i-1]+f[i-2];
maxm=f[a[1]],minm=f[a[1]],maxw=a[1],minw=a[1];
int j=2;a[n+1]=i+2;
while (a[j]<=i)
{
if (f[a[j]]>maxm) maxm=f[a[j]],maxw=a[j];
if (f[a[j]]<minm) minm=f[a[j]],minw=a[j];
j++;
}
if (a[n]>i) maxw=a[n];
}
print(maxw),putchar(' '),print(minw),puts("");
}
return 0;
}

## 搜索--BFS

### 小X的密室

#### 分析

$f[i][j]$表示到$i$号房间，钥匙的状态为$j$的最少步数

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#define LL long long

using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

{
char c=nc();int len=1;
for(;!(c>='a' && c<='z');c=nc()) if (c==EOF) return 0;
for(;(c>='a' && c<='z');s[len++]=c,c=nc());
s[len++]='\0';
return len-2;
}

for (x=nc();!(x>='A' && x<='Z');x=nc());
}

int wt,ss[19];
inline void print(int x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {
for (wt=0;x;ss[++wt]=x%10,x/=10);
for (;wt;putchar(ss[wt]+48),wt--);}
}
inline void print(LL x){
if (x<0) x=-x,putchar('-');
if (!x) putchar(48); else {for (wt=0;x;ss[++wt]=x%10,x/=10);for (;wt;putchar(ss[wt]+48),wt--);}
}

int n,m,k,a[5010],f[5010][2010];
struct data
{
int x,a;
data(int A=0,int B=0):x(A),a(B){}
};
vector<data> b[5010];
struct dp
{
int x,a,c;
dp(int A=0,int B=0,int C=0):x(A),a(B),c(C){}
};
queue<dp> q;
bool v[5010][2010];

int main()
{
freopen("room.in","r",stdin);
freopen("room.out","w",stdout);
int x,y,z,u;
for (int i=1;i<=n;i++)
{
x=0;
for (int j=1;j<=k;j++)
a[i]=x;
}
for (int i=1;i<=m;i++)
{
for (int j=1;j<=k;j++)
b[x].push_back(data(y,z));
}
for (int i=1;i<=n;i++)
for (int j=0;j<=1050;j++)
f[i][j]=m*1000,v[i][j]=false;
q.push(dp(1,a[1],0));
f[1][a[1]]=0;v[1][a[1]]=true;
while (!q.empty())
{
x=q.front().x;y=q.front().a;z=q.front().c;q.pop();
for(int i=0;i<b[x].size();i++)
{
//			print(b[x][i].a),puts("");
if ((y&b[x][i].a)==b[x][i].a)
{
f[b[x][i].x][y|a[b[x][i].x]]=min(f[x][y]+1,f[b[x][i].x][y|a[b[x][i].x]]);
if (!v[b[x][i].x][y|a[b[x][i].x]]) v[b[x][i].x][y|a[b[x][i].x]]=true,
q.push(dp(b[x][i].x,y|a[b[x][i].x],f[b[x][i].x][y|a[b[x][i].x]]));
}
}
}
int ans=f[n][0];
for (int i=1;i<=1050;i++)
ans=min(ans,f[n][i]);
if (ans==m*1000) puts("No Solution");
else print(ans),puts("");
return 0;
}
posted @ 2017-11-07 19:50  Xiejiadong  阅读(...)  评论(...编辑  收藏
levels of contents