A. Suffix Three
#include<bits/stdc++.h>
using namespace std;
int main()
{
int _;cin>>_;while(_--)
{
string s;
cin>>s;
int len=s.size()-1;
if(s[len]=='o') puts("FILIPINO");
else if(s[len]=='u') puts("JAPANESE");
else puts("KOREAN");
}
}
B. Azamon Web Services
直接把第一串变成能达到的最小串,如果连最小的串都不能大于第二个串就没办法更小了。。
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+10;
string s,t;
int main()
{
int _;cin>>_;while(_--)
{
cin>>s>>t;
int n=s.size()-1;
int m=t.size()-1;
for(int i=0;i<=n;++i){
int p=i;
for(int j=n;j>i;--j){
if(s[j]<s[p]) p=j;
}
if(p!=i) {
swap(s[i],s[p]);
break;
}
}
if(s<t) cout<<s<<endl;
else puts("---");
}
}
C. Cut and Paste
感觉C比B好想,由于x<1e6,那么小于x就暴力即可,大于1e6就可以用数学公式代替了。。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
const ll mod=1e9+7;
int x;
string s;
int main()
{
int _;cin>>_;while(_--)
{
scanf("%d",&x);
cin>>s;
ll l=0;
ll n=s.size();
while(l<x){
if(s.size()<x){
int d=s[l]-'0'-1;
ll t=d;
string tmp=s.substr(l+1);
ll len=tmp.size();
while(d--) s+=tmp;
n=(n+len*t%mod)%mod;
}
else{
n=((l+1)%mod+(1ll*n-l-1+mod)%mod*(s[l]-'0')%mod)%mod;
}
++l;
}
printf("%lld\n",n);
}
}
D. Beingawesomeism
这题比C还水,答案就0,1,2,3,4,MORTAL。。二维前缀和搞搞就可以了。。
#include<bits/stdc++.h>
using namespace std;
const int N=70;
int vis[N][N],sum[N][N];
char s[N][N];
int n,m;
int main()
{
int _;cin>>_;while(_--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) vis[i][j]=0;
int f=0;
for(int i=1;i<=n;++i){
scanf("%s",s[i]+1);
for(int j=1;j<=m;++j)
if(s[i][j]=='A') vis[i][j]=1,f=1;
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
sum[i][j]=vis[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
if(sum[n][m]==n*m){
printf("0\n");
continue;
}
int ans=-1;
if(sum[1][m]==m||sum[n][m]-sum[n-1][m]==m||sum[n][1]==n||sum[n][m]-sum[n][m-1]==n)
ans=1;
if(ans!=-1){
printf("%d\n",ans);
continue;
}
if(s[1][1]=='A'||s[1][m]=='A'||s[n][1]=='A'||s[n][m]=='A') ans=2;
if(ans!=-1){
printf("%d\n",ans);
continue;
}
for(int i=1;i<=n;++i) if(sum[i][m]-sum[i-1][m]==m) ans=2;
for(int i=1;i<=m;++i) if(sum[n][i]-sum[n][i-1]==n) ans=2;
if(ans!=-1){
printf("%d\n",ans);
continue;
}
for(int i=1;i<=n;++i) if(s[i][1]=='A'||s[i][m]=='A') ans=3;
for(int i=1;i<=m;++i) if(s[1][i]=='A'||s[n][i]=='A') ans=3;
if(ans!=-1){
printf("%d\n",ans);
continue;
}
if(f) printf("4\n");
else printf("MORTAL\n");
}
}
E. Jeremy Bearimy
题意 :给你2*k个点,用2*k-1条边连接成一棵树,现你要选择k对点,每对点之间有一个距离,问你如何分配k对点,求得k对点的距离之和 的 最大值 和最小值
这题可能稍微有点难度,但是花点时间 也好想其实。。。
求最大值,对于每一条边要使更多对的人经过该边,最大为min(2∗k−子树的size,子树的size) min(2*k-子树的size,子树的size)min(2∗k−子树的size,子树的size),dfs求子树的size然后乘边权加入答案即可。
求最小值,如果一个节点连了偶数个未被算的节点(不算上父节点),那么显然这偶数个节点互相连接最小。如果一个节点连了奇数个还未被算的节点(不算父节点),那么显然这个节点和他连着的节点相连更小。dfs即可
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
vector<int>G[N],val[N];
ll mx,mi;
int vis[N],n,dp[N];
void dfs(int u,int fa)
{
//printf("u:%d\n",u);
dp[u]=1;
ll s1=0;
int num=0;
for(int i=0;i<G[u].size();++i)
{
int v=G[u][i];
if(v==fa) continue;
int w=val[u][i];
dfs(v,u);
dp[u]+=dp[v];
mx=(mx+1ll*min(dp[v],n-dp[v])*w);
if(vis[v]==0){
vis[v]=1;
num++;
s1+=w;
}
}
if(num%2==0) mi+=s1;
else mi+=s1,vis[u]=1;
}
int main()
{
int _;cin>>_;while(_--)
{
scanf("%d",&n);
int m=2*n-1;
n=2*n;
mx=mi=0;
for(int i=1;i<=n;++i) G[i].clear(),val[i].clear(),vis[i]=0,dp[i]=0;
for(int i=1;i<=m;++i) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
G[u].push_back(v);
G[v].push_back(u);
val[u].push_back(w);
val[v].push_back(w);
}
dfs(1,0);
printf("%lld %lld\n",mi,mx);
}
}