传送门:点我
A 石子序列
相邻的不同,第一个位置有m种可能,以后的每个位置有m-1种可能
#include<iostream>
using namespace std;
#define mod 1000000007
typedef long long ll;
int main(){
int n,m;
cin>>n>>m;
ll sum=m;
for(int i=1;i<n;i++){
sum=sum*(m-1);
sum=sum%mod;
}
cout<<sum<<endl;
}
B 凤凰
看根节点的那一个树枝儿孙最多,用深搜,
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000000+100;
int head[maxn],tot;
struct Edge{
int to,next;
}edge[maxn<<1];
void adde(int u, int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
edge[tot].to=u;
edge[tot].next=head[v];
head[v]=tot++;
}
int son[maxn];
int Max;
void DFS(int u,int fa){
son[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
Edge e=edge[i];
int v=e.to;
if(v==fa) continue;
DFS(v,u);
son[u]+=son[v];
if(u==1) Max=max(Max,son[v]);
}
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
head[i]=-1;
}
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
adde(u,v);
}
DFS(1,-1);
printf("%d\n",Max);
}
C PH 试纸
直接开两个数组分别记录位置
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1000000+10;
int r[maxn],b[maxn];
int main(){
int n,m;
scanf("%d%d",&n,&m);
char str[maxn];
getchar();
scanf("%s",str+1);
getchar();
int countr=1;
int countb=1;
for(int i=1;i<=n;i++){
if(str[i]=='R'){
r[countr++]=i;
}
else{
b[countb++]=i;
}
}
char ch;
int lin;
for(int i=0;i<m;i++){
scanf("%c %d",&ch,&lin);
getchar();
if(ch=='R'&&r[lin]!=0){
printf("%d\n",r[lin]);
}
else if(ch=='R'&&r[lin]==0){
printf("-1\n");
}
else if(ch=='B'&&b[lin]!=0){
printf("%d\n",b[lin]);
}
else{
printf("-1\n");
}
}
}
D 插排树
深搜
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=50000+100;
int head[maxn],tot;
struct Edge{
int to,next;
}edge[maxn];
int dis[maxn],len[maxn];
int Max;
int du[maxn];
void DFS(int u,int fa){
for(int i=head[u];i!=-1;i=edge[i].next){
Edge e=edge[i];
int v=e.to;
if(v==fa) continue;
dis[v]=dis[u]+len[v];
DFS(v,u);
Max=max(Max,dis[v]);
}
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) head[i]=-1;
for(int i=1;i<n;i++){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
edge[tot].to=u;
edge[tot].next=head[v];
head[v]=tot++;
len[u]=c;
du[u]++;
}
int root;
for(int i=1;i<=n;i++) if(du[i]==0) root=i;
dis[root]=0;
DFS(root,-1);
printf("%d\n",Max);
}
E 青蛙
直接用dijkstra 最短路跑的
#include <iostream>
using namespace std;
#define MAX 9999999
#define LEN 300
int map[LEN][LEN]; //某点到某点两点间的的距离
int dist[LEN]; //记录当前点到源点的最短路径长度
int mark[LEN]; //加入进来的点的集合
//初始化map为正无穷大
void init(){
int i,j;
for(i=0;i<LEN;i++){
for(j=0;j<LEN;j++){
map[i][j]=MAX;
}
}
}
//n:多少条路 start:起始点
void myDijstra(int n,int start){
int i,j,min,k;
for(i=1;i<=n;i++){
mark[i]=0;//没有点加入
dist[i]=map[start][i];//初始
}
mark[start]=1;//把起始点加进来
dist[start]=0;
for(i=1;i<=n;i++){
min=MAX;
for(j=1;j<=n;j++){
if(!mark[j] && dist[j]<min){ //取出不在mark里的最小的dist[i]
min=dist[j];
k=j;//标记
}
}
if(min==MAX)
break;
mark[k]=1;//把K加进来
//做松弛操作
for(j=1;j<=n;j++){
if(!mark[j] && dist[j]>dist[k]+map[k][j]){
dist[j]=dist[k]+map[k][j];
}
}
}
}
int main(){
int i,j,n,line;
int a,b,d;
cin>>n>>line; //输入点和边
init();
for(i=0;i<line;i++){
cin>>a>>b; //输入各边的权值
if(map[a][b]>1){
map[a][b]=1;
}
}
for(i=0;i<n;i++){
map[i][i+1]=1;
map[i+1][i]=1;
}
myDijstra(n,0);//调用方法
cout<<dist[n]<<endl;
return 0;
}
F 三轮
感觉像完全背包,
但是都说正解是分治fft …好吧并不会
#include<iostream>
#include<vector>
using namespace std;
#define mod 19260817
const int maxn=100000+100;
int dp[maxn],ans[maxn];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&ans[i]);
}
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=ans[i];j<=m;j++){
dp[j]=(dp[j]+dp[j-ans[i]])%mod;
}
}
int sum=0;
for(int i=1;i<=m;i++){
sum=(sum+dp[i])%mod;
}
printf("%d\n",sum);
}