【B】后缀数组
【C】染色,DP(感觉可出)
【D】BFS搜索,有点麻烦
【G】概率DP+状态压缩
【I】矩阵快速幂(队友已出)
【J】树的分治
【A】
Post Robot
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
But there is such few comments of his posts that he feels depressed all the day. As his best friend and an excellent programmer, DT asked you to help make his blog look more popular. He is so warm that you have no idea how to refuse. But you are unwilling to read all of his boring posts word by word. So you decided to write a script to comment below his posts automatically.
After observation, you found words “Apple” appear everywhere in his posts. After your counting, you concluded that “Apple”, “iPhone”, “iPod”, “iPad” are the most high-frequency words in his blog. Once one of these words were read by your smart script, it will make a comment “MAI MAI MAI!”, and go on reading the post.
In order to make it more funny, you, as a fan of Sony, also want to make some comments about Sony. So you want to add a new rule to the script: make a comment “SONY DAFA IS GOOD!” when “Sony” appears.
The size of the article does not exceed 8KB.
Apple bananaiPad lemon ApplepiSony Tim cook is doubi from Apple
iPhoneipad
iPhone30 is so biiiiiiig Microsoft
makes good App.
【Sample Output】
MAI MAI MAI!
MAI MAI MAI!
MAI MAI MAI!
SONY DAFA IS GOOD!
MAI MAI MAI!
MAI MAI MAI!
MAI MAI MAI!
【分析】
Game
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
● In the beginning of the game, there are a lot of piles of beads.
● Players take turns to play. Each turn, player choose a pile i and remove some (at least one) beads from it. Then he could do nothing or split pile i into two piles with a beads and b beads.(a,b > 0 and a + b equals to the number of beads of pile i after removing)
● If after a player's turn, there is no beads left, the player is the winner.
Suppose that the two players are all very clever and they will use optimal game strategies. Your job is to tell whether the player who plays first can win the game.
For each test case, the first line contains a postive integer n(n < 105) means there are n piles of beads. The next line contains n postive integer, the i-th postive integer ai(ai < 231) means there are ai beads in the i-th pile.
【Sample Output】
Win
Lose
Lose
【题意】
Dice
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
At the beginning, the two dices may face different(which means there exist some i, ai ≠ bi). Ddy wants to make the two dices look the same from all directions(which means for all i, ai = bi) only by the following four rotation operations.(Please read the picture for more information) Now Ddy wants to calculate the minimal steps that he has to take to achieve his goal.
For each case, the first line consists of six integers a1,a2,a3,a4,a5,a6, representing the numbers on dice A.
The second line consists of six integers b1,b2,b3,b4,b5,b6, representing the numbers on dice B.
【Sample Output】
-
【题意】
/* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : F1006
************************************************ */ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; typedef struct nod{
int a,b,c,d,e,f;
} node; node move1(node a)
{
node ret;
ret.a=a.d;ret.b=a.c;ret.c=a.a;
ret.d=a.b;ret.e=a.e;ret.f=a.f;
return ret;
} node move2(node a)
{
node ret;
ret.a=a.c;ret.b=a.d;ret.c=a.b;
ret.d=a.a;ret.e=a.e;ret.f=a.f;
return ret;
} node move3(node a)
{
node ret;
ret.a=a.f;ret.b=a.e;ret.c=a.c;
ret.d=a.d;ret.e=a.a;ret.f=a.b;
return ret;
} node move4(node a)
{
node ret;
ret.a=a.e;ret.b=a.f;ret.c=a.c;
ret.d=a.d;ret.e=a.b;ret.f=a.a;
return ret;
} node q[];
int num[];
int head=,tail=; bool check(node a)
{
for (int i=;i<=tail;i++)
if (a.a==q[i].a&&a.b==q[i].b&&a.c==q[i].c&&a.d==q[i].d&&a.e==q[i].e&&a.f==q[i].f)
return true;
return false;
} int main()
{
node a,b;
while (scanf("%d",&a.a)!=EOF)
{
scanf("%d%d%d%d%d",&a.b,&a.c,&a.d,&a.e,&a.f);
scanf("%d%d%d%d%d%d",&b.a,&b.b,&b.c,&b.d,&b.e,&b.f); if (a.a==b.a&&a.b==b.b&&a.c==b.c&&a.d==b.d&&a.e==b.e&&a.f==b.f)
{
printf("0\n");
} else
{
q[]=a;
num[]=;
bool done=false;
head=;tail=;
while (head<=tail)
{
node temp=move1(q[head]);
if (temp.a==b.a&&temp.b==b.b&&temp.c==b.c&&temp.d==b.d&&temp.e==b.e&&temp.f==b.f)
{
printf("%d\n",num[head]+);
done=true;
break;
}
if (!check(temp))
{
tail++;
q[tail]=temp;
num[tail]=num[head]+;
} temp=move2(q[head]);
if (temp.a==b.a&&temp.b==b.b&&temp.c==b.c&&temp.d==b.d&&temp.e==b.e&&temp.f==b.f)
{
printf("%d\n",num[head]+);
done=true;
break;
}
if (!check(temp))
{
tail++;
q[tail]=temp;
num[tail]=num[head]+;
} temp=move3(q[head]);
if (temp.a==b.a&&temp.b==b.b&&temp.c==b.c&&temp.d==b.d&&temp.e==b.e&&temp.f==b.f)
{
printf("%d\n",num[head]+);
done=true;
break;
}
if (!check(temp))
{
tail++;
q[tail]=temp;
num[tail]=num[head]+;
} temp=move4(q[head]);
if (temp.a==b.a&&temp.b==b.b&&temp.c==b.c&&temp.d==b.d&&temp.e==b.e&&temp.f==b.f)
{
printf("%d\n",num[head]+);
done=true;
break;
}
if (!check(temp))
{
tail++;
q[tail]=temp;
num[tail]=num[head]+;
} head++;
}
if (!done) printf("-1\n");
}
} return ;
}
代码写得也比较丑
【启发】
当时初看题目的时候瞟了几眼直接就跳过了,-_-///事后感觉没什么可以做了才回来看的,然后才发现其实很简单。还是应该认真看看题,比赛的时候至少每道题都要看过去,说不定能找到一些突破点。
【H】
Number Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Special Judge
● ai ∈ [0,n] ● ai ≠ aj( i ≠ j )
For sequence a and sequence b, the integrating degree t is defined as follows(“⊕” denotes exclusive or):t = (a0 ⊕ b0) + (a1 ⊕ b1) +···+ (an ⊕ bn) (sequence B should also satisfy the rules described above)
Now give you a number n and the sequence a. You should calculate the maximum integrating degree t and print the sequence b.
For each case, the first line contains an integer n(1 ≤ n ≤ 105), The second line contains a0,a1,a2,...,an.
【Sample Output】
【题意】
题目给出一组A序列,t的值是等于B序列中的每一个对应的数与A序列异或之后的和。现在的要求就是求出能够使得t最大的B序列。
【分析】
首先我真的不是特别明白这道题为什么会用到Special Judge?
......按照我的想法,能使得t最大的B序列应该是唯一的,把所有数都化为二进制的形式,则为了使得Ai异或Bi的值最大,Bi的二进制数位要尽可能多地与Ai错开。
所以这样出来的数其实是一组两个的数,A序列是从0到n,B序列也是从0到n,且每个序列不出现重复的数字。对于每一个Ai,用一个等长的全1的二进制数去与之异或,就能得到对应的Bi,反过来对数Bi操作可以得到数Ai。其实就是构造出来之后使对应的Ai+Bi能等于一个全是1的二进制数。
如此就能构造出B序列了,下面是几个序列的对应关系,T这行表示异或结果
n=
-------------------
A B T
-------------------
n=
-------------------
A B T
-------------------
n=
-------------------
A B T
-------------------
当然这里有个顺序的问题,构造的时候从最大(二进制最长的数)的开始向小的数进行,保证使最终总的异或值最大,并且后来构造出来Bi的数比Ai小,避免了异或构造出来的数大于n的情况(真的可能会有啊)。
/* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : H1008
************************************************ */ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; int pp[]={,,,,,,,,,,,,,,,,,};
int a[],b[]; int get(int s)
{
int ret=;
while (s>)
{
ret++;
s/=;
}
return ret;
} int main()
{
//freopen("H1008.txt","r",stdin);
//freopen("H1008out.txt","w",stdout); int n;
while (scanf("%d",&n)!=EOF)
{
memset(a,,sizeof(a));
for (int i=n;i>=;i--)
if (!a[i])
{
for (int j=i;j>=pp[get(i)-]+;j--)
{
int yh=j^pp[get(i)];
a[j]=yh;
a[yh]=j;
}
} long long ans=;
int x;
for (int i=;i<=n;i++)
{
scanf("%d",&x);
//x=i;
ans+=(long long )x^a[x];
b[i]=a[x];
}
printf("%lld\n",ans);
printf("%d",b[]);
for (int i=;i<=n;i++) printf(" %d",b[i]);
printf("\n");
} return ;
}
【启发】
虽然当时还没想明白Special Judge是为什么(现在还是不明白...),不过以后碰到有思路的就直接上吧,说不定就对了呢。
【K】
Ellipsoid
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Special Judge
For each testcase, one line contains 6 real number a,b,c(0 < a,b,c,< 1),d,e,f(0 ≤ d,e,f < 1), as described above. It is guaranteed that the input data forms a ellipsoid. All numbers are fit in double.
0.04 0.01
【Sample Output】
1.0000000
【题意】
题目给出一个椭圆面的空间方程,要求计算出原点与椭圆面之间的最短距离。
【分析】
/* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : HDU5017-Easy Simulated Annealing
************************************************ */ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; double a,b,c,d,e,f;
double r=0.99;
double eps=1e-;
int dx[]={-,-,-,,,,,};
int dy[]={-,,,-,,-,,}; double cal(double x,double y)
{
double A=c,B=e*x+d*y,C=a*x*x+b*y*y+f*x*y-;
double delta=B*B-*A*C;
if (delta<) return 1e60;
double z1=(-B+sqrt(delta))//A,z2=(-B-sqrt(delta))//A;
if (z1*z1<z2*z2) return z1;
else return z2;
} double dis(double x,double y,double z)
{
return sqrt(x*x+y*y+z*z);
} double doit()
{
double step=;
double x=,y=,z;
while (step>eps)
{
z=cal(x,y);
for (int i=;i<;i++)
{
double xx=x+dx[i]*step,yy=y+dy[i]*step;
double zz=cal(xx,yy);
if (zz>1e30) continue;
if (dis(xx,yy,zz)<dis(x,y,z))
{
x=xx;
y=yy;
z=zz;
}
}
step*=r;
}
return dis(x,y,z);
} int main()
{
while (scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e,&f)!=EOF)
printf("%.8f\n",doit());
return ;
}
个人认为这种搜索策略与真正的模拟退火算法还是有一点区别的,首先这里面根本没有涉及到向非最优解方向移动的情况。
我的理解是,这里模仿了模拟退火算法对温度控制的特性。由于是求解原点与椭球面的距离,这个结果必然是一个凸函数,则不断修正前进的方向并逐步缩小搜索范围,最终到达最优解。
首先指定一个步长与步长衰减速度(类退火速度),每次搜索完成一层,步长衰减一次,直到衰减程度在精度控制范围内。
三分:
二分用来求解线性函数的最优值,三分则是用来求解凸函数的最优值。
对于本题来说,基本想法是以x,y,z中的其中两个变量进行两次三分,而后计算出第三个变量,并以最终的距离作为判断函数。由于这里都是实数,两层三分需要迭代的次数比较难以控制,参数稍微修正得不对,精度与时间上就会出现比较大的问题,这两个要求的参数是对立的,精度高了耗时就长,时间控制了,可能最终结果又错了。
最后提交的是在超时边缘......中间出现了许多重复运算,这种还是不推荐使用了。