====== 2020/07/18--2020/07/24======
----
===== 团队训练 =====
暂无
----
===== 王瑞琦 =====
===比赛===
无
===专题===
无
===== 冯宇扬 =====
没有
===== 常程 =====
===比赛===
没有
===专题===
这一周在刷AC自动机的题来着,所以没有新的东西
----
===== 本周推荐 =====
==== 王瑞琦 ====
翻出来以前写的一道模拟退火入门题,温习了一下。
===来源===
洛谷P1337:[[https://www.luogu.com.cn/problem/P1337|平衡点]]
===标签===
模拟退火,数学
===题意===
给出桌面上n个洞的坐标,n个重物系绳分别穿过n个洞,求绳结最后的平衡位置。
===题解===
绳结平衡,即所受n个力达到平衡。\\
而当绳结处于一个非平衡点时,其所受合力方向必指向最后的平衡点,因此我们将绳结向该方向移动一段距离。\\
循环上述过程,每次移动的距离逐渐减少,最终绳结将“逼近”最后的平衡点。\\
#include
#include
#define abs(x) ((x) >= 0 ? (x) : (-(x)))
#define true 1
#define false 0
int main()
{
int a[34][1001]={0};
int n;
int XF=true, YF=true;
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d%d%d",&a[1][i],&a[2][i],&a[3][i]);
double t=5000,tx,ty;
double x=1,y=1;
while (true)
{
tx=x;
ty=y;
double lx=0,ly=0,dist;
for (int i=1;i<=n;i++)
{
dist=sqrt((a[2][i]-y)*(a[2][i]-y)+(a[1][i]-x)*(a[1][i]-x));
if (dist==0) continue;
lx=lx+a[3][i]/dist*(a[1][i]-x);
ly=ly+a[3][i]/dist*(a[2][i]-y);
}
dist=sqrt(lx*lx+ly*ly);
x=x+t/dist*lx;
y=y+t/dist*ly;
if (abs(tx-x)<0.00001&&abs( ty - y)<0.00001) break;
if ((XF!=(x>tx))||(YF!=(y>ty))){
XF=1-(x>tx);
YF=1-(y>ty);
t=t*0.9;
}
}
printf("%.3lf %.3lf",x,y);
getchar();
getchar();
return 0;
}
===comment===
比较入门的一道题,复习的时候却调了好久=。=\\
关于模拟退火还在学习当中...
==== 冯宇扬 ====
本周完全摸鱼
==== 常程 ====
=== 来源 ===
[[https://www.luogu.com.cn/problem/P4052|p4052 文本生成器]]
=== 标签 ===
AC自动机 DP
=== 题意 ===
给出一些模式串和一个长度,求出给定长度下至少包含一个给出的模式串的文本串数量。
=== 思路 ===
这道题可以通过计算不包含任何一个模式串的文本串数量间接求解。\\
主要是在Trie树上运用dp。
在这里我想做题的人需要对文本串在Trie树上匹配的过程有一个直观而清晰的认识——匹配到当前的树上的位置代表一切其fail一串上的均可以匹配,但以该点为fail的位置不能被匹配。\\
运用dp,dp[i][j]表示 长度为i、结点序号为j的位置不包含任何一个模式串的文本串数量。\\
状态转移方程为:dp[i+1][son[j][k]]+=dp[i][j] (!flag[son[j][k])\\
这里面需要注意的是,如果一个结点是一个模式串的末尾,那么以其为fail关系的子孙的结点都要标记flag,原因如上。
#include
#include
using namespace std;
int n,m,tot=1,dp[6005][105],mod=10007;
char s[105];
struct unit{int s[27],fail,flag;}T[6005];
void Insert()
{
int root=1,id;
for(int i=0;s[i];i++)
{
id=s[i]-65;
if(!T[root].s[id])
T[root].s[id]=++tot;
root=T[root].s[id];
}
T[root].flag=1;
}
void get_fail()
{
for(int i=0;i<26;i++)
T[0].s[i]=1;
T[1].fail=0;
queueq;
q.push(1);
int m=1,head;
while(m--)
{
head=q.front();
q.pop();
for(int i=0,v,fafail;i<26;i++)
{
v=T[head].s[i];
fafail=T[head].fail;
if(!v) T[head].s[i]=T[fafail].s[i];
else
{
T[v].fail=T[fafail].s[i];
T[v].flag|=T[T[v].fail].flag;
q.push(v);
m++;
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
Insert();
}
get_fail();
dp[1][0]=1;
for(int i=1;i<=m;i++)
for(int j=1;j<=tot;j++)
for(int k=0;k<26;k++)
if(!T[T[j].s[k]].flag)
dp[T[j].s[k]][i]=(dp[T[j].s[k]][i]+dp[j][i-1])%mod;
int ans=1;
for(int i=26,j=m;j;j>>=1,i=(i*i)%mod)
if(j&1)
ans=(ans*i)%mod;
for(int i=1;i<=tot;i++)
ans=(ans-dp[i][m]+mod)%mod;
printf("%d",ans);
return 0;
}
=== comment ===
还算是有点复杂的,当时调了一段时间。