20190922CSP-S模拟

这个是USACO 2019 JAN Gold的原题,可能因为过于水,所以我即使八点多才开始做也提前ak。。。来写一篇题解。。

A.Cow Poetry

显然押同一韵的行只需要最后一个词属于一个韵部,前面长度$K-s_i$随便排,DP一下长度$i$的有多少种,类似于背包转移,只是把物品放在内层,容量放在外层枚举,这样保证顺序不同时有不同的种类数。

然后对于每一种要求韵相同的行,可以枚举每一种韵,结合乘法原理和加法原理得出方案数。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define dbg(x) cerr << #x << " = " << x <<endl
 7 using namespace std;
 8 typedef long long ll;
 9 typedef double db;
10 typedef pair<int,int> pii;
11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
16 template<typename T>inline T read(T&x){
17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
19 }
20 const int N=5000+7,P=1e9+7;
21 char opt[3];
22 int f[N],now;
23 int cnt[27],typ[N];
24 int s[N],c[N];
25 int n,m,k,maxc,ans=1;
26 inline void add(int&A,int B){A+=B;A>=P&&(A-=P);}
27 inline int fpow(int x,int p){int ret=1;for(;p;p>>=1,x=x*1ll*x%P)if(p&1)ret=ret*1ll*x%P;return ret;}
28 
29 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
30     read(n),read(m),read(k);
31     for(register int i=1;i<=n;++i)read(s[i]),MAX(maxc,read(c[i]));
32     for(register int i=1;i<=m;++i)scanf("%s",opt),++cnt[opt[0]-'A'];
33     f[0]=1;
34     for(register int i=0;i<=k;++i)
35         for(register int j=1;j<=n;++j)if(i+s[j]<=k)add(f[i+s[j]],f[i]);
36     for(register int i=1;i<=n;++i)if(k>=s[i])add(typ[c[i]],f[k-s[i]]);
37     for(register int i=0;i<26;++i)if(cnt[i]){
38         int tmp=0;
39         for(register int j=1;j<=maxc;++j)if(typ[j]){
40             add(tmp,fpow(typ[j],cnt[i]));
41         }
42         ans=ans*1ll*tmp%P;
43     }
44     printf("%d\n",ans);
45     return 0;
46 }
View Code

B. Sleepy Cow Sorting

这个真的水。。可以发现显然最后最长的有序上升序列不要动,把前面的数不断往后插,这样就保证了次数最少。于是BIT维护一发即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define dbg(x) cerr << #x << " = " << x <<endl
 7 using namespace std;
 8 typedef long long ll;
 9 typedef double db;
10 typedef pair<int,int> pii;
11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
16 template<typename T>inline T read(T&x){
17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
19 }
20 const int N=1e5+7;
21 int C[N];
22 int a[N];
23 int n,las,pos;
24 #define lowbit(x) x&(-x)
25 inline void add(int x){for(;x<=n;x+=lowbit(x))++C[x];}
26 inline int sum(int x){int ret=0;for(;x;x-=lowbit(x))ret+=C[x];return ret;}
27 
28 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
29     read(n);
30     for(register int i=1;i<=n;++i)read(a[i]);
31     las=a[n];add(las);pos=n-1;
32     for(register int i=n-1;i;--i)if(MIN(las,a[i]))--pos,add(a[i]);else break;
33     printf("%d\n",pos);
34     for(register int i=1;i<=pos;++i)printf("%d ",pos-i+sum(a[i])),add(a[i]);
35     puts("");return 0;
36 }
View Code

C. Shortcut

每个点到根的最短路路径是唯一的(因为字典序已经要求最小的),所以构成的最短路树就是唯一的,于是跑一遍dijkstra记录父边(注意更新min)之后在最短路树上暴力枚举把哪个和根相连,计算贡献取max即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #define dbg(x) cerr << #x << " = " << x <<endl
 8 using namespace std;
 9 typedef long long ll;
10 typedef double db;
11 typedef pair<int,int> pii;
12 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
13 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
14 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
15 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
16 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
17 template<typename T>inline T read(T&x){
18     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
19     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
20 }
21 const int N=1e5+7;
22 struct thxorz{int to,nxt,w;}G[N];
23 int Head[N],tot,c[N];
24 int n,m,t;
25 inline void Addedge(int x,int y,int z){
26     G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;
27     G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot,G[tot].w=z;
28 }
29 int dis[N],fa[N],val[N];
30 priority_queue<pii,vector<pii>,greater<pii> > q;
31 #define y G[j].to
32 inline void dij(){
33     memset(fa,0x3f,sizeof fa);
34     memset(dis,0x3f,sizeof dis);q.push(make_pair(dis[1]=0,1));
35     while(!q.empty()){
36         int d=q.top().first,x=q.top().second;q.pop();
37         if(dis[x]^d)continue;
38         for(register int j=Head[x];j;j=G[j].nxt)
39             if(d+G[j].w==dis[y]&&MIN(fa[y],x))val[y]=G[j].w;
40             else if(d+G[j].w<dis[y])q.push(make_pair(dis[y]=d+G[j].w,y)),fa[y]=x,val[y]=G[j].w;
41     }
42 }
43 ll ans=0;
44 int dfs(int x,int fa,int dep){
45     int siz=c[x];
46     for(register int j=Head[x];j;j=G[j].nxt)if(y^fa)siz+=dfs(y,x,dep+G[j].w);
47     MAX(ans,(dep-t)*1ll*siz);
48     return siz;
49 }
50 #undef y
51 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
52     read(n),read(m),read(t);
53     for(register int i=1;i<=n;++i)read(c[i]);
54     for(register int i=1,x,y,z;i<=m;++i)read(x),read(y),read(z),Addedge(x,y,z);
55     dij();memset(Head,0,sizeof Head);tot=0;
56     for(register int i=2;i<=n;++i)Addedge(i,fa[i],val[i]);
57     dfs(1,0,0);
58     printf("%lld\n",ans);
59     return 0;
60 }
View Code

猜你喜欢

转载自www.cnblogs.com/saigyouji-yuyuko/p/11566642.html