A题:https://ac.nowcoder.com/acm/contest/369/A
题目描述
"我明白。"
作为这命运剧场永远的观众,小D一直注视着这片星光璀璨的舞台,舞台上,少女们的身姿演绎出了一幕幕动人的场景,令人回味无穷。
有的时候,小D也会自己写一些歌曲,来加入Starlight的剧本,使得剧本充满了新的生命力。
现在小D又要准备写乐谱了,小D写谱的方式比较独特。他会先写出一个按照音符出现顺序排成的序列,再进一步整合,每次整合会选取相邻的三个作为三和弦。整合次数无限。
小D选取的音符形如D5 F6这种形式,例如D5表示D大调sol(这里不考虑升降音)为了方便生成乐谱,他将这些音符进一步转化了,小D给C D E F G A B重新编号成了1 2 3 4 5 6 7,之后新的音符编号生成方式应为(字母对应的标号-1)*7+数字,例如
但小D讨厌一些他所认为的不优美的和弦,因此他并不希望自己的谱子里面有可能出现这样的三和弦,也就说音符组成的序列里不应该存在他所讨厌的子段,假如C5 F1 A2这三个音符凑成的和弦小D不喜欢,那么序列里面就不能出现C5 F1 A2,C5 A2 F1,A2 C5 F1,A2 F1 C5,F1 A2 C5,F1 C5 A2这六种子段。
现在小D正在推算有多少合法的序列,答案对 取模。
星屑飘洒的舞台上,可人绽放的爱之花,请努力让大家星光闪耀吧!
暴力dp.....,窝还需多写题目鸭。dp[i][j][k]表示已经在第i位了并且后两位的数字为j,k的方案数。
#include
using namespace std;
typedef long long ll;
#define mod 1000000007
ll can[51][51][51],dp[501][51][51];
int n,q;
int main()
{
for(int i=0;i<50;i++){
for(int j=0;j<50;j++){
for(int k=0;k<50;k++){
can[i][j][k]=1;
}
}
}
scanf("%d %d",&n,&q);
int xx,yy,zz;
for(int e=1;e<=q;e++){
scanf("%d %d %d",&xx,&yy,&zz);
can[xx][yy][zz]=can[xx][zz][yy]=can[yy][xx][zz]=can[yy][zz][xx]=can[zz][xx][yy]=can[zz][yy][xx]=0;
}
dp[0][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<50;j++){
for(int k=0;k<50;k++){
for(int l=1;l<50;l++){
dp[i][k][l]=(dp[i][k][l]+can[j][k][l]*dp[i-1][j][k])%mod;
}
}
}
}
ll ans=0;
for(int i=1;i<50;i++){
for(int j=1;j<50;j++){
ans+=dp[n][i][j];
ans%=mod;
}
}
printf("%lld\n",ans%mod);
return 0;
}
C题:https://ac.nowcoder.com/acm/contest/369/C
小A给你了一棵树,对于这棵树上的每一条边,你都可以将它复制任意(可以为0)次(即在这条边连接的两个点之间再加一条边权相同的边),求所有可能新形成的图中欧拉路的最短长度
欧拉路:从图中任意一个点开始到图中任意一个点结束的路径,并且图中每条边只通过恰好一次
答案即为所有边权的两倍和减去树的直径,注意边权加和时要用long long。
官方题解:
先考虑回路的情况。由于是一棵树,任两点间路径只有一条,从一条边走到深度更大的点,一定还会从同一条边返回以回到起点或者遍历其他子树,所以每条边需要复制一次,此时答案是边权和的两倍。
不是回路的情况可以减掉从终点回到起点的路径,要让这条路径尽量长,所以长度一定是直径的长度。
#include
using namespace std;
int n;
typedef long long ll;
const int N=222222;
ll dist[N];
vector < pair >edge[N];
void dfs(int u,int fa,ll p)
{
dist[u]=p;
for(auto &it: edge[u]){
if(it.first!=fa){
dfs(it.first,u,p+it.second);
}
}
}
int main()
{
scanf("%d",&n);
int u,v;
ll ans=0,w;
for(int i=1;i