A_石子序列:
这个题和BZOJ的越狱一模一样,就是简单的组合数学问题。
一排石子,第一个可以有M种选择,第二个有M-1种选择,然后后面的以此都是那样。
这个题目唯一的考点可能就是快速幂吧。
ans= M* qpow( M - 1 , N- 1 );
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
template <class T>
void read( T & x){
x=0;ll f=1;char c=getchar();
for( ; !isdigit(c); c=getchar()){ if(c=='-') f=-1;}
for( ; isdigit(c); c=getchar()){ x=x*10+c-'0';}
}
ll qpow(ll a,ll b){
ll ans=1;
while(b){
if(b&1){
ans=ans*a%mod;
}
b>>=1;
a=a*a%mod;
}
return ans;
}
int main()
{
ll n,m;
read(n),read(m);
ll ans=(m*qpow(m-1,n-1))%mod;
printf("%lld\n",ans);
}
B_凤凰:
这个题目真的有意思,我想了一会,不太好想,因为我想到可能和某个位置的子节点个数有关吧,
后来看了题解,联系了出题人,问了一波,我就发现这个题真的挺好想的。
首先容易证明每一只鸟可能会在排队,
如果没有排队那么说明此时它的子节点都是没有鸟的。
然后一秒都有根节点相连的节点个数K,每秒都有K只输送,
然而K关键不是看总个数,而是关注在过来时候受限制的位置。
所以影响时间的因素关键是:与1(根节点)相连的子树大小。
然而我在看正确的代码中出现了我没讲过的骚操作。
首先贴上代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
template <typename T>
void read(T &x){
x=0;int f=1;char c=getchar();
for(; !isdigit(c);c=getchar()) {if(c=='-') f=-1;}
for(; isdigit(c);c=getchar()) {x=x*10+c-'0';}
}
vector <int>G[N];
int n,x,y;
int dfs(int x,int pre=1){
int cnt=1;
for(auto &to:G[x]){
if(to!=pre){
cnt+=dfs(to,x);
}
}
return cnt;
}
int main()
{
read(n);
for(int i=1;i<=n-1;i++){
read(x);read(y);
G[x].push_back(y);
G[y].push_back(x);
}
int ans=0;
for(auto & to:G[1]){
ans=max(ans,dfs(to));
}
return 0*printf("%d\n",ans);
}
其中for( auto & v :G[ x ] )意思是
for( int i = 0; i< G[x] .size ();i++){
auto v=G[ x ][ i ];
}
还有自己看出来的并查集找子树。
#include<bits/stdc++.h>
using namespace std;
const int N=1000050;
template<class T>
void read(T& x){
x=0;int f=1;char c=getchar();
for(; !isdigit(c);c=getchar()){ if(c=='-'){f=-1;}}
for(; isdigit(c);c=getchar()){ x=x*10+c-'0';}
}
int pre[N];
int fa(int x){ return pre[x]==x?x:pre[x]=fa(pre[x]);}
void Union(int x,int y){ x=fa(x);y=fa(y);pre[x]=y;}
int x,y,n,fu,fv;
int ans=0,cnt[N];
int main()
{
read(n);
for(int i=1;i<=n;i++){
pre[i]=i;
}
for(int i=1;i<=n-1;i++){
read(x);read(y);
if(x!=1&&y!=1){
x=fa(x),y=fa(y);
pre[x]=y;
}
}
/*for(int i=1;i<=n;i++){
printf("%d %d\n",i,pre[i]);
}*/
for(int i=1;i<=n;i++){
++cnt[fa(i)];
}
for(int i=1;i<=n;i++){
ans=max(ans,cnt[i]);
}
printf("%d\n",ans);
return 0;
}
C—PH 试纸
简单的模拟询问题,只要开两个数组,把对应的位置记录即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000005;
template <class T>
void read(T &x){
int f=1;char c=getchar();
for( ; !isdigit(c); c=getchar()) {if(c=='-') f=-1;}
for( ; isdigit(c); c=getchar()) { x=x*10+c-'0';}
}
int R[N],B[N];
char s[N],c;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(R,-1,sizeof(R));
memset(B,-1,sizeof(B));
int cntR=0,cntB=0;
scanf("%s",s);
for(int i=0;i<n;i++){
if(s[i]=='R') R[++cntR]=i+1;
else B[++cntB]=i+1;
}
//printf("%s\n",s+1);
int t;
for(int i=1;i<=m;i++){
scanf("%s%d",s,&t);
if(s[0]=='R')
printf("%d\n",R[t]);
else
printf("%d\n",B[t]);
}
return 0;
}
D—插排树
这个题目就是考查你会不会把最短路的模板改成最长路罢了。
我的做法:模板Dijstra 堆优化。
#include<bits/stdc++.h>
using namespace std;
const int N=50050;
template <class T>
void read(T &x){
x=0;int f=1;char c=getchar();
for( ; !isdigit(c);c=getchar()){ if(f=='-') f=-1;}
for( ; isdigit(c);c=getchar()){ x=x*10+c-'0';}
}
typedef struct node{
int to,w,next;
}Edge;
Edge edge[N];
int head[N],cnt,dis[N],ans=-1;
void add_edge(int u,int v,int w){
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
struct Cmp{
bool operator ()(int a,int b){
return dis[a]>dis[b];
}
};
void dijstra(int S){
memset(dis,128,sizeof(dis));
dis[S]=0;
priority_queue<int,vector<int> ,Cmp >q;
q.push(S);
while(!q.empty()){
int cur=q.top();
q.pop();
for(int i=head[cur];~i;i=edge[i].next){
int to=edge[i].to;
int w=edge[i].w;
if(dis[to]<dis[cur]+w){
dis[to]=dis[cur]+w;
ans=max(dis[to],ans);
q.push(to);
}
}
}
printf("%d\n",ans);
}
int n,du[N],x,y,w;
int main()
{
memset(du,0,sizeof(du));
memset(head,-1,sizeof(head));
read(n);
for(int i=1;i<=n-1;i++){
read(x),read(y),read(w);
add_edge(y,x,w);
du[x]++;
}
/*for(int i=1;i<=n;i++){
if(du[i]==0){
printf("####%d\n",i);
}
}*/
for(int i=1;i<=n;i++){
if(du[i]==0){
dijstra(i);break;
}
}
return 0;
}
E——青蛙
这个题挺有意思的,本来是DP写的,由于时间关系,我到时肯定会贴回来的DP做法。
然后我的做法是建边跑一个SPFA。
#include<bits/stdc++.h>
using namespace std;
const int N=505;
template <class T>
void read( T &x){
x=0;int f=1;char c=getchar();
for(;!isdigit(c);c=getchar()){if(c=='-')f=-1;}
for(; isdigit(c);c=getchar()){x=x*10+c-'0';}
}
int L,n,cnt,x,y,w,dis[N],vis[N],head[N];
typedef struct Edge{
int to,next,w;
}Edge;
Edge e[N];
void add_edge(int u,int v,int w=1){
e[cnt].to=v;
e[cnt].next=head[u];
e[cnt].w=1;
head[u]=cnt++;
}
void SPFA(int S){
memset(dis,127,sizeof(dis));
vis[S]=1;
dis[S]=0;
queue<int>q;
q.push(S);
while(!q.empty()){
int cur=q.front();
q.pop();
vis[cur]=0;
for(int i=head[cur];~i;i=e[i].next){
int to=e[i].to,w=e[i].w;
if(dis[to]>dis[cur]+w){
dis[to]=dis[cur]+w;
if(vis[to]==0){
vis[to]=1;
q.push(to);
}
}
}
}
printf("%d\n",dis[L]);
}
int main()
{
memset(head,-1,sizeof(head));
read(L),read(n);
for(int i=0;i<=L-1;i++){
add_edge(i,i+1);
add_edge(i+1,i);
}
for(int i=1;i<=n;i++){
read(x),read(y);
add_edge(x,y);
}
SPFA(0);
return 0;
}
F——三轮
压轴题:考察了FFT来优化。但是我不会,所以给自己挖一个坑,当我会的时候就是我AC的时候了。