A(签到)
题意:签到
00:01 1A
#include <bits/stdc++.h> using namespace std; typedef long long int LL; #define st first #define nd second #define pb push_back #define mp make_pair #define pll pair <LL, LL> #define pii pair <int, int> #define rep(i,x) for(int i=1;i<=x;i++) const int N = 1e5+7; const int MX = 1e9+7; const LL INF = 1e18+9LL; int main(){ int x; cin>>x; if(x==2)cout<<2; else cout<<1; }
B(构造)
题意:有长度为n的数列B,Ai表示B中与Bi不同的值的数量,给出数列A,求B
显然
1若Ai不同则Bi一定不同
2一定有n-Ai个数等于Bi
推出相同Ai的个数一定是n-Ai的倍数,其中每组n-Ai个Bi相等,否则无解,有解时方案按之前推论构造即可。
这题开始还没想出来,不应该。。
01:12 2A
#include <bits/stdc++.h> using namespace std; typedef long long int LL; #define st first #define nd second #define pb push_back #define mp make_pair #define pll pair <LL, LL> #define pii pair <int, int> #define rep(i,x) for(int i=1;i<=x;i++) const int N = 1e5+7; const int MX = 1e9+7; const LL INF = 1e18+9LL; int a[N],sum[N],ans[N],lim[N]; vector<int> b[N]; int main(){ int n; cin>>n; rep(i,n){ scanf("%d",&a[i]); b[a[i]].pb(i); sum[a[i]]++; } for(int i=0;i<n;i++){ if(sum[i]%(n-i)){ cout<<"Impossible"; return 0; } lim[i]=n-i; } cout<<"Possible"<<endl; int cnt=1; for(int i=0;i<n;i++){ for(int j=0;j<b[i].size();j++){ ans[b[i][j]]=cnt; if((j+1)%lim[i]==0)cnt++; } } rep(i,n)cout<<ans[i]<<" "; return 0; }
C(dp)
题意:给n个方格涂m种颜色,有k个方格和左边的方格颜色不同,求方案数。(n<=2000,m<=2000)
f[i][j]=f[i-1][j]+(m-1)*f[i-1][j-1],输出f[n][k]即可。数组可以滚动,但没必要。O(nk)
或者直接推公式也不难
00:23 1A
#include <bits/stdc++.h> using namespace std; typedef long long int LL; #define st first #define nd second #define pb push_back #define mp make_pair #define pll pair <LL, LL> #define pii pair <int, int> #define rep(i,x) for(int i=1;i<=x;i++) const int N = 2e3+7; const int MX = 1e9+7; const LL INF = 1e18+9LL; const LL mod=998244353; LL dp[N][N]; int main(){ int n,m,k; cin>>n>>m>>k; dp[0][0]=1; rep(i,n) for(int j=0;j<i&&j<=k;j++){ if(j==0){ dp[i][j]=m; continue;} dp[i][j]=((dp[i-1][j-1]*(m-1))%mod+dp[i-1][j])%mod; } cout<<dp[n][k]; }
D(MST)
题意:给出一个加权无向图,有k个特殊结点。定义路径长度为路径上的最大边权,求这k个结点到其他特殊结点最短路的最大值。
定义开始看起来很绕,后来一想其实类似货车运输。首先最短路一定在最小生成树上取到,观察样例可以猜想所有最大值相等。事实上,考虑kruskal算法过程,当一条边被加入时,如果他两边的并查集都含有特殊结点,那么答案一定不比这条边小,因为树上的路径唯一,两边的特殊结点间的路径一定包含这条边,据此也可发现所有结点的答案一定都相等。所以只需在kruskal执行时维护每个并查集的大小,当有一个并查集大小为k时,说明所有特殊结点一已经联通,之后的边都不会影响答案,而最后一条边一定连接了两个特殊结点,所以这条边的权值就是所有的最大值。