BEGIN-4(Fibonacci数列)
有递推公式,大家都知道用递推公式求,只要记得在递推的时候同时取模求好
这里给一份另类代码,用矩阵快速幂求,其实还有循环节
/*
(1 1) * (Fn-1) = ( Fn )//矩阵相乘,将就着看吧
(1 0) (Fn-2) (Fn-1)
(1 1) * (1 1) * (Fn-2) = ( Fn )
(1 0) (1 0) (Fn-3) (Fn-1)
F1=1,F0=0...
(1 1) * ... * (1 1) * (1) = ( Fn )//共n-1个(1 1)
(1 0) (1 0) (0) (Fn-1) (1 0)
*/
#include
const int Mod=10007;
int Z[2][2];
void Matrix_Multiply(int X[][2],int Y[][2]){
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
Z[i][j]=0;
for(int k=0;k<2;k++)
Z[i][j]+=X[i][k]*Y[k][j];
}
}
}
void Matrix_Copy(int *C){
for(int i=0;i<2*2;i++)
C[i]=Z[i/2][i%2]%Mod;
}
int Fast(int n){//快速求幂
int B[2][2]={1,0,0,1,},A[2][2]={1,1,1,0};//B为单位矩阵
while(n){
if(n&1){
Matrix_Multiply(B,A);
Matrix_Copy(&B[0][0]);
}
n>>=1;
Matrix_Multiply(A,A);
Matrix_Copy(&A[0][0]);
}
return B[0][0];//B[0][0]*f1+B[0][1]*f0 (f1=1,f0=0)
}
int main()
{
int n;
scanf("%d",&n);
n=(n-1)%20016+1;//实验发现循环节为20016,其实在使用快速幂的情况下这个优化快不了多少
printf("%d\n",Fast(n-1));
return 0;
}
BASIC-1(闰年判断)
#include
bool Is(int y){
if(y%4)return false;
if(y%100)return true;
if(y%400)return false;
return true;
}
int main()
{
int y;
scanf("%d",&y);
printf("%s\n",Is(y)?"yes":"no");
return 0;
}
BASIC-2(01字串)
回溯就好
#include
#define MAXN 5
int ans[MAXN];
void Print_ans(int k){
for(int i=0;i
BASIC-3(字母图形)
#include
int main()
{
char ans[26][26];
for(int i=0;i<26;i++){//这样把最大图案存好就不会错了,黑黑
ans[i][i]='A';
for(int j=i+1;j<26;j++)
ans[i][j]=ans[j][i]='A'+j-i;
}
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i
BASIC-4(数列特征)
懒得思考了,最大最小值 直接存下标了
int main()
{
int minid,maxid,sum,n,a[10010];
minid=maxid=sum=0;
scanf("%d",&n);
for(int i=0;ia[maxid])maxid=i;
if(a[i]
BASIC-5(查找整数)
每个数都不大于10000,可在输入时储存每个数字第一次出现的位置,后面的查找就变成了O(1)
#include
int a[10010];
int main()
{
int n,c;
scanf("%d",&n);
for(int i=1;i<=n+1;i++){
scanf("%d",&c);
if(a[c]==0)a[c]=i;
}
printf("%d\n",a[c]>n?-1:a[c]);//这里a[c]>n表示c只在最后输入查询值时出现过
return 0;
}
BASIC-6(杨辉三角形)
不多说了,注意格式就好
#include
int main()
{
int n,f[35][35];
scanf("%d",&n);
for(int i=0;i
BASIC-7(特殊的数字)
是不是很逗
#include
int main()
{
printf("153\n370\n371\n407\n");
return 0;
}
BASIC-8(回文数)
还去写什么判断语句真是弱爆了
#include
int main()
{
for(int i=1;i<10;i++)
for(int j=0;j<10;j++)
printf("%d%d%d%d\n",i,j,j,i);
return 0;
}
BASIC-9(特殊回文数)
两份代码,后者比前者快
#include
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<10;i++)
for(int j=0;j<10;j++){
int k=n-i*2-j*2;
if(k>=0 && k<10)
printf("%d%d%d%d%d\n",i,j,k,j,i);}
if(n%2==0){
n/=2;
for(int i=1;i<10;i++)
for(int j=0;j<10;j++){
int k=n-i-j;
if(k>=0 && k<10)
printf("%d%d%d%d%d%d\n",i,j,k,k,j,i);}
}
return 0;
}
#include
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n/2&&i<10;i++)
for(int j=0;j<=n/2-i&&j<10;j++){
int k=n-i*2-j*2;
if(k<10)
printf("%d%d%d%d%d\n",i,j,k,j,i);}
if(n%2==0){
n/=2;
for(int i=1;i<=n&&i<10;i++)
for(int j=0;j<=n-i&&j<10;j++){
int k=n-i-j;
if(k<10)
printf("%d%d%d%d%d%d\n",i,j,k,k,j,i);}
}
return 0;
}
BASIC-10(十进制转十六进制)
#include
int main()
{
int n;
scanf("%d",&n);
printf("%X\n",n);//注意X
return 0;
}
BASIC-11(十六进制转十进制)
#include
int main()
{
long long n;
scanf("%I64X",&n);
printf("%I64d\n",n);
return 0;
}
BASIC-12(十六进制转八进制)
一位16进制对应四位2进制,一位8进制对应三位2进制,三位16进制对应四位8进制(也可以六位对应八位....)
#include
#include
int getnu(char c){
if(c>='0' && c<='9')return c-'0';
return c-'A'+10;
}
void putans(char *s){
int ans=0;
for(int i=0;i<3;i++)
ans=ans*16+getnu(s[i]);
printf("%04o",ans);
}
int main()
{
int n;
char a[100010];
scanf("%d",&n);
for(int i=0;i
BASIC-13(数列排序)
你们老师有没有教sort(),我们老师没有
#include
#include
using namespace std;
int main()
{
int a[210],n;
scanf("%d",&n);
for(int i=0;i
ALGO-1(区间k大数查询)
排序啊 排序
View Code
ALGO-2(最大最小公倍数)
不纠结,题目数据有问题
顺带提:此题是丽洁桑高中时在CF上出的题146A
#include
//1-n中取三个数
int main()
{
long long n,ans;
scanf("%I64d",&n);
if(n<3)ans=n;
else{
if(n&1)ans=n*(n-1)*(n-2);
else{
if(n%6==0)ans=(n-1)*(n-2)*(n-3);
else ans=n*(n-1)*(n-3);
}
}
printf("%I64d\n",ans);
return 0;
}
ALGO-3(K好数)
DP 先存下第n-1位为0-(k-1)分别的个数,根据第n-1位为0-(k-1)的个数推出第n位为0-(k-1)的个数,最后对第L位的0-(k-1)分别的个数求和
#include
#include
using namespace std;
const int Mod=1000000007;
int main()
{
int k,l,dp[110][110]={0},ans=0;
scanf("%d%d",&k,&l);
if(l<2)ans=k*l;//我觉得这里的k不应该减一,但是题目中这里的k需要减掉1才能过掉第一组数据(好坑)
else{
dp[0][1]=0;
for(int i=1;i
ALGO-4(节点选择)
树形DP 从图中任选一点作为根节点,得到生成树,再在生成树上从叶子节点向上DP
#include
#include
#include
using namespace std;
#define MAXN 100010
int Head[MAXN],Head0[MAXN],n,V[MAXN],D[MAXN],Son[MAXN],GSon[MAXN],mk=0;
bool f[MAXN];
struct EdgeNode{
int to,next;
}Edges[MAXN],Edges0[MAXN<<1];
void DFS(int s){//递归
int k=Head[s];
D[s]=V[s];
while(k>=0){
if(D[Edges[k].to]<0)DFS(Edges[k].to);
Son[s]+=D[Edges[k].to];
GSon[s]+=Son[Edges[k].to];
k=Edges[k].next;
}
D[s]=max(D[s]+GSon[s],Son[s]);
}
void GtoT(int u){//生成树
int k=Head0[u];
while(k>=0){
if(!f[Edges0[k].to]){
f[Edges0[k].to]=true;
Edges[mk].to=Edges0[k].to;
Edges[mk].next=Head[u];
Head[u]=mk;
mk++;
GtoT(Edges0[k].to);
}
k=Edges0[k].next;
}
}
void Swap(int &a,int &b){
int c=a;
a=b;
b=c;
}
int main()
{
int u,v;
scanf("%d",&n);
memset(Head,-1,sizeof(Head));
memset(Head0,-1,sizeof(Head0));
memset(D,-1,sizeof(D));
memset(Son,0,sizeof(Son));
memset(GSon,0,sizeof(GSon));
for(int i=1;i<=n;i++)scanf("%d",&V[i]);
for(int i=0;i<2*n-2;i++){//生成图,双向
scanf("%d%d",&u,&v);
Edges0[i].to=v;
Edges0[i].next=Head0[u];
Head0[u]=i++;
Swap(u,v);
Edges0[i].to=v;
Edges0[i].next=Head0[u];
Head0[u]=i;
}
memset(f,false,sizeof(f));
f[1]=true;//图中任选一点,这里选结点1
GtoT(1);
DFS(1);
printf("%d\n",D[1]);
return 0;
}
ALGO-5(最短路)
存在负边所以不能用Dijkstra,SPFA比Bellman-Ford快,赤裸裸的套模版
#include
#include
#define MAXN 20010
#define MAXM 200010
#define INF 200000
int Head[MAXN],n,m,Dist[MAXN];
struct EdgeNode{
int to,w,next;
}Edges[MAXM];
void SPFA(int s){//题目说不存在负环,所以没实现判断负环存在功能
int Que[MAXN],Iq=0;
bool Visit[MAXN];
for(int i=0;i<=n;i++)Dist[i]=INF;
memset(Visit,false,sizeof(Visit));
Dist[s]=0;
Visit[s]=true;
Que[Iq++]=s;
int Id=0;
while(Id!=Iq){
int top=Que[Id];
Visit[top]=false;
int k=Head[top];
while(k>=0){
if(Dist[Edges[k].to]>Edges[k].w+Dist[top]){
Dist[Edges[k].to]=Edges[k].w+Dist[top];
if(!Visit[Edges[k].to]){
Que[Iq++]=Edges[k].to;
Visit[Edges[k].to]=true;
}
}
k=Edges[k].next;
}
Id++;
}
}
int main()
{
int u,v,l;
scanf("%d%d",&n,&m);
memset(Head,-1,sizeof(Head));
for(int i=0;i
ALGO-6(安慰奶牛)
题目关键在于如何转换成构建最小生成树的形式
假如现在我们已经生成了最小生成树,不难发现:
1.一个节点有几个度,就需要访问该节点(牧场)的奶牛几次+访问一次过夜牧场的奶牛
2.每条边(路)都要走两次
如此便可进行转换:
每条边的权可改为:走该条路需要的时间*2+路两端的奶牛交谈需要的时间
即:Li*2+C[Si]+C[Ei]
然后运行一遍最小生成树
过夜牧场自然选择与奶牛交谈时间最少的
#include
#include
#include
using namespace std;
const int MAXM=100010;
const int MAXN=10010;
int f[MAXN];
int find(int x){
if(f[x]==x)return x;
return find(f[x]);
}
void Merge(int x,int y){
f[y]=x;
}
struct Edge{
int a,b,v;
}e[MAXM];
bool cmp(Edge a,Edge b){
return a.v
ALGO-7(逆序对)
平衡树,SBT;外加一些分治,回溯思想,一顿胡搞。
先求同一颗树下两颗子树分别的逆序对数,然后求两颗子树交换前后两者间的逆序对数,取小值,递归求和。
先上未整理的杂乱代码
#include
#include
using namespace std;
#define MAXN 200005
int n,m;
long long ans;
//SBT,Size Blance Tree
int S[MAXN],Left[MAXN],Right[MAXN];
unsigned int Key[MAXN];
int Left_Rotate(int rt){
int k=Right[rt];
Right[rt]=Left[k];
Left[k]=rt;
S[k]=S[rt];
S[rt]=S[Left[rt]]+S[Right[rt]]+1;
return rt=k;
}
int Right_Rotate(int rt){
int k=Left[rt];
Left[rt]=Right[k];
Right[k]=rt;
S[k]=S[rt];
S[rt]=S[Left[rt]]+S[Right[rt]]+1;
return rt=k;
}
int Maintain(int rt,bool flag){
if(flag){
if(S[Left[Right[rt]]]>S[Left[rt]] || S[Right[Right[rt]]]>S[Left[rt]]){
if(S[Left[Right[rt]]]>S[Left[rt]])Right[rt]=Right_Rotate(Right[rt]);
return Left_Rotate(rt);
}
}
else{
if(S[Right[Left[rt]]]>S[Right[rt]] || S[Left[Left[rt]]]>S[Right[rt]]){
if(S[Right[Left[rt]]]>S[Right[rt]])Left[rt]=Left_Rotate(Left[rt]);
return Right_Rotate(rt);
}
}
return rt;
}
int Insert(int rt,int RT){
S[rt]+=1;
if(Key[RT]>Key[rt]){
if(Right[rt]>0)Right[rt]=Insert(Right[rt],RT);
else{
Right[rt]=RT;
}
}
else{
if(Left[rt]>0)Left[rt]=Insert(Left[rt],RT);
else{
Left[rt]=RT;
}
}
return rt=Maintain(rt,Key[RT]>Key[rt]);
}
int Rank(int rt,int v){
if(v>Key[rt]){
if(Right[rt]==0)return S[rt];
return S[rt]-S[Right[rt]]+Rank(Right[rt],v);
}
if(Left[rt]==0)return 0;
return Rank(Left[rt],v);
}
int Merge(int rt,int Start,int End){
long long lans=0,rans=0;
for(int i=Start;i<=End;i++){
lans+=Rank(rt,Key[i]);
rans+=S[rt]-Rank(rt,Key[i]+1);
}
for(int i=Start;i<=End;i++){
S[i]=1;
Left[i]=Right[i]=0;
rt=Insert(rt,i);
}
ans+=min(lans,rans);
return rt;
}
int Init(){
int v;
scanf("%d",&v);
if(v){
Key[++m]=v;
S[m]=1;
Left[m]=Right[m]=0;
return m;
}
int TL,TR,Ls,Le,Rs,Re;
Ls=m+1;
TL=Init();
Le=m;
Rs=m+1;
TR=Init();
Re=m;
if(S[TL]
用红黑树拓展一下应该过也没问题
ALGO-8(操作格子)
线段树(实现区间最大值查询O(logn))+树状数组(实现区间求和查询O(logn))
#include
#include
#include
using namespace std;
#define MAXN 100001
int s=1,n,Seg[MAXN<<2],BIT[MAXN];
void Seg_RefUp(int i,int c){//线段树更新O(logn)
Seg[i]=c;
while(i>1){
i>>=1;
int e=Seg[i];
Seg[i]=max(Seg[i<<1],Seg[i<<1|1]);
if(e==Seg[i])return;
}
}
void BIT_RefUp(int k,int c){//树状数组更新O(logn)
while(k<=n){
BIT[k]+=c;
k+=k&-k;
}
}
void BuildSegAndBIT(){//建线段树和树状数组(时间复杂度和空间复杂度实际上都是O(n))
memset(Seg,0,sizeof(Seg));
memset(BIT,0,sizeof(BIT));
while(s0){
ans+=BIT[b];
b-=b&-b;
}
a--;
while(a>0){
ans-=BIT[a];
a-=a&-a;
}
return ans;
}
int Seg_Query(int a,int b,int k,int l,int r){//线段数查询O(logn)
if(a<=l && b>=r)return Seg[k];
if(a>r || b>1),Seg_Query(a,b,(k<<1)+1,((l+r)>>1)+1,r));
}
int main()
{
int m,p,x,y;
scanf("%d%d",&n,&m);
BuildSegAndBIT();
for(int i=0;i
ADV-1(两条直线)
对所有坐标按(x+y,x-y)排序,反过来排也行,然后用O(n)时间求前i个坐标的最大最小x-y和后i个坐标的最大最小x-y
然后二分搜索最小答案,在判断二分出的值是否满足正确性时,根据(x+y)的递增性可以再应用一次二分
#include
#include
using namespace std;
#define MAXN 100010
int n;
double lmin[MAXN],lmax[MAXN],rmin[MAXN],rmax[MAXN];//lmin[i],lmax[i]分别存前i个x-y的最大最小值,相应的rmin[],rmax[]你们懂
struct hmd{
int aa,bb;
double a,b;
}e[MAXN];
bool cmp(hmd p,hmd q){
if(p.aa!=q.aa)
return p.aaans*2
int m=(l+j)/2;
if(e[m].a-e[i].a>ans*2)j=m;
else l=m+1;
}
int d=0;
double Min=0,Max=0;
if(i>0){
Min=lmin[i-1];
Max=lmax[i-1];
d=1;
}
if(j=0;i--){
rmin[i]=min(rmin[i+1],e[i].b);
rmax[i]=max(rmax[i+1],e[i].b);
}
double L=0,R=1e9;
while(R-L>1e-2){//二分搜索最小的最大曼哈顿距离的值
double M=(L+R)/2;
if(Is(M))R=M;
else L=M;
}
printf("%.1lf\n",L);
return 0;
}
ADV-2
无
ADV-3(金属采集)
以S为根节点向下深搜,回溯向上DP
dp[x][i]表示在以x为根节点的子树上用i个机器人采集时的最小花费
jqr[x]存当前以x为根节点的子树上最多可以jqr[x]个机器人
当两颗子树a,b汇到同一父亲c节点上时
dp[c][i]=min(dp[a][j]+dp[b][k]+k*(c节点到b节点的距离))(c节点到a节点的距离为0;j+k=i;j<=jqr[a],k<=jqr[b])
dp[c][0]=以c为根节点的子树上的所有边的边权*2的和
#include
#include
#include
#include
using namespace std;
#define MAXN 100010
int head[MAXN],dp[MAXN][11],du[MAXN],jqr[MAXN],n,s,k,m;
bool vis[MAXN];
struct Edge{
int to,next,w;
}e[MAXN<<1];
void add_edge(int u,int v,int c){
e[m].to=v;
e[m].w=c;
e[m].next=head[u];
head[u]=m++;
}
void dfs(int x,int w){
vis[x]=true;
if(du[x]==1 && x!=s){//为了方便判断叶子节点,这里用到了节点的度 (一课树上度为1的是叶子节点,根节点除外)
jqr[x]=1;//叶子节点初始化一个不工作的机器人
dp[x][0]+=w*2;// dfs()最后一行解释
return;
}
int d=head[x];
while(d>=0){
int y=e[d].to;
if(!vis[y]){
dfs(y,e[d].w);
for(int i=min(k,jqr[x]+jqr[y]);i>0;i--){
int xf,count=0;
for(int a=min(i,jqr[y]);a>=0;a--){
int b=i-a;
if(b>jqr[x])break;//x是x的一颗距离为0的子树
if(count>0)xf=min(xf,dp[x][b]+dp[y][a]+e[d].w*a);
else{
xf=dp[x][b]+dp[y][a]+e[d].w*a;
count++;
}
}
dp[x][i]=xf;
}
dp[x][0]+=dp[y][0];
jqr[x]+=jqr[y];
}
d=e[d].next;
}
dp[x][0]+=w*2;//为了方便写转移方程,将父亲节点到其某一子树根节点的距离累加到子树上,这样到该子树上的距离为0
}
void work(){
dfs(s,0);
int ans=dp[s][0];
for(int i=1;i<=k && dp[s][i]>0;i++)if(dp[s][i]
ADV-4(道路和航路)
有道路连接的点都属于强连通块
并查集储存强连通块
航路是强连通块间的有向道路
航路指向的强连通块入度加1
依次求入度为0的强连通块内点的最短路,然后更新该块发出的航路的连接点,接着去掉该航路(相应入度减1)
并查集+链式前向星存图
优先队列+Dijkstra求最短路
#include
#include
#include
using namespace std;
const int MAXN=25010;
const int MAXE=150010;
int head[MAXN],size,HEAD[MAXN],SIZE;
struct Edge{
int to,next,w;
}edge[MAXE],EDGE[50010];
void edge_Add(int u,int v,int l){
edge[size].to=v;
edge[size].w=l;
edge[size].next=head[u];
head[u]=size++;
}
void EDGE_Add(int u,int v){
EDGE[SIZE].to=v;
EDGE[SIZE].next=HEAD[u];
HEAD[u]=SIZE++;
}
int par[MAXN],rank[MAXN];
int find(int x){
if(x==par[x])return x;
return par[x]=find(par[x]);
}
void merge(int x,int y){
x=find(x);
y=find(y);
if(x==y)return;
if(rank[x] < rank[y])par[x]=y;
else{
par[y]=x;
if(rank[x]==rank[y])rank[y]++;
}
}
bool isvis[MAXN];
void DFS_isvis(int s){
isvis[s]=true;
for(int k=head[s];k>=0;k=edge[k].next)if(!isvis[edge[k].to])DFS_isvis(edge[k].to);
}
int indegree[MAXN],dist[MAXN];
bool p[MAXN];
void Dijkstra(int s){
queue degree0;
priority_queue > heap;
dist[s]=0;
heap.push(make_pair(0,s));
while(!heap.empty() || !degree0.empty()){
if(heap.empty()){
int u=degree0.front();
degree0.pop();
for(int k=HEAD[u];k>=0;k=EDGE[k].next){
int v=EDGE[k].to;
heap.push(make_pair(-dist[v],v));
}
}else{
int u=heap.top().second;
heap.pop();
if(p[u])continue;
p[u]=true;
for(int k=head[u];k>=0;k=edge[k].next){
int v=edge[k].to;
if(!p[v] && dist[v]>dist[u]+edge[k].w){
dist[v]=dist[u]+edge[k].w;
if(find(u)==find(v))heap.push(make_pair(-dist[v],v));
}
if(find(u)!=find(v)){
indegree[find(v)]--;
if(indegree[find(v)]==0)degree0.push(find(v));
}
}
}
}
}
int main()
{
int n,r,p,s,a,b,c,d=0,U[50010],V[50010];
scanf("%d%d%d%d",&n,&r,&p,&s);
for(int i=1;i<=n;i++){
par[i]=i;
rank[i]=0;
head[i]=HEAD[i]=-1;
}
for(int i=0;i
ADV-5(最小方差生成树)
不纠结,题目数据有问题(求VIP给的),目测第4到第6组也有问题,第2到第3组肯定有问题
一份粗糙代码
#include
#include
#include
using namespace std;
#define MAXN 55
#define MAXM 1010
int n,m,U[MAXM],V[MAXM],f[MAXN],Case;
double W[MAXM],Min,Max,cw[MAXN];
struct edge{
int id;
double wf;
}e[MAXM];
bool cmp(edge a,edge b){
return a.wfMax)Max=W[i];
if(W[i]
PREV-1(核桃的数量)
#include
int gcd(int x,int y){//求x,y两者的最大公约数
int z;
while(y){
z=x%y;
x=y;
y=z;
}
return x;
}
int main()
{
int a,b,c,ans;
scanf("%d%d%d",&a,&b,&c);
ans=a*b/gcd(a,b);//a,b,c<30
ans=ans*c/gcd(ans,c);
printf("%d\n",ans);
return 0;
}
PREV-2(打印十字图)
没什么好说的,渣渣填充二维数组
#include
#define MAX 125
int main()
{
char g[MAX][MAX],a='$',b='.';
int n,center=63;
for(int i=0;i
PREV-3(带分数)
详解:
http://www.cnblogs.com/cshhr/p/3584271.html
PREV-4
不多说,我是弱渣做不出,虽然我过了
PREV-5(错误票据)
看了数据范围(不大于100000),果断定义数组,不用排序,不用比较,速度妥妥的
sstream是老师教的
#include
#include
#include
#include
using namespace std;
int f[100010];
int main()
{
int n,max=0,min=100010,c;
string s;
scanf("%d",&n);
getline(cin,s);
for(int i=0;i>c){
f[c]++;
if(cmax)max=c;
}
}
for(int i=min;i
PREV-6(翻硬币)
贪心,字符从头到尾一个个判断,不一样就翻
#include
#include
int main()
{
int ans=0;
char a[1010],b[1010];
scanf("%s%s",&a,&b);
for(int i=0;i
PREV-7(连号区间数)
n<=50000,判断每个区间[l,r]先求最大最小值,再求差,时间复杂度为O(3*(r-l)),区间[l,r]可以从[l,r-1]递推上路判断,所以总的时间复杂度为O(n^2)
本以为会有几组数据超时,结果全过了。弱渣想不到并查集如何运用T>. 看了锦囊,这比用并查集还快? PREV-8(买不到的数目) a*b-a-b望大神贡献证明过程 PREV-9(大臣的旅费) 详解: http://www.cnblogs.com/cshhr/p/3584271.html PREV-10(幸运数) 模拟取幸运数过程 弱渣想问,用堆如何来做 普通二分搜索树的建立,打印的格式要注意的地方是每个数的字符串形式的长度 PREV-12(危险系数) 枚举除x,y外的n-2个点,除去枚举点所连的所有边,对除枚举点外所有的点生成树 PREV-13(网络寻路) 枚举每条边作为两转发点的联通路径 PREV-14(高僧斗法) 博弈(hdu1850可以去看看) PREV-15(格子刷油漆) DP PREV-16 无 PREV-17(约数倍数卡片) dfs深搜,目测最后一组数据有错... PREV-18 无 PREV-19(九宫重排) bfs广搜,把九宫中的'.'换成'9',这样每种状态就可以转换成一个9位整数表示,共9^9种状态, 用平衡树set容器维护已搜索的状态 队列维护已搜索到但未进行下一步搜索的状态 从初始状态开始广搜,每次遇到一种新状态时,把新状态存入平衡树set容器中,并加入到队列队尾 每次搜到一种状态判断是否已存在,如果存在不管它,继续搜索下一个状态 如果搜索到的状态是目标状态,停止搜索,如果队列为空,停止搜索 不难看出,每种状态最多搜索一次,时间复杂度最大为O(9!*lg(9!)) PREV-20 无 分类: 渣渣的世界#include
#include
现初始化取出所有奇数(题目中,第二个位置的数被两次作为选数基数)
每次剔除非幸运数时,未被剔除的数的当前位置应及时减去前面的被剔除个数
因为按照规律,两幸运数相隔应该不是很大,
所以查询一个数的不大于她的一个最近幸运数的位置应该很简单#include
PREV-11(横向打印二叉树)#include
#include
枚举的边的两点的其他度相乘 便是以该两点作为转发点所有路径数,记得通信是双向的#include
#include
/*
当n>1时,刷油漆可以分为5个状态
顺序为a->b->c->d
或a->b->...->c->d(状态3)
状态1)(可由状态1,2得来)
..ac ..ab
..db ..dc
状态2)(可由状态2,3,4,5得来)
..bc ..bd ..ad ..ac
..ad ..ac ..bc ..bd
状态3)(可由状态3得来)
..ba ..ca
..cd ..bd
状态4)(可由状态2得来)
..ba ..dc
..dc ..ba
状态5)(可由状态2得来)
..ad ..cb
..cb ..ad
*/
#include
#include