contest1305
A.Kuroni and the Gifts
题意
给两个长度为n的数组a[],b[],保证在每个数组内任意两个元素不同,要求重新排列两个数组内元素使得对于任意 i , j i,j i,j有 a i + b i ! = a j + b j a_i+b_i!=a_j+b_j ai+bi!=aj+bj,输出重新排列的两个数组。
思路
直接对两个数组排序分别输出即可。
AC代码
#include
#include
#include
#include
#include
#include
#define MOD 1000000007
using namespace std;
int main()
{
int t,n;
int a[105],b[105];
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)scanf("%d",&b[i]);
sort(a+1,a+n+1);sort(b+1,b+n+1);
for(int i=1;i<=n;i++)printf("%d ",a[i]);
printf("\n");
for(int i=1;i<=n;i++)printf("%d ",b[i]);
printf("\n");
}
return 0;
}
B. Kuroni and Simple Strings
题意
给定一个仅由“(”和“)”组成的字符串,定义一个括号序列为简单序列当且仅当:
题解
显然最多只要删除1次。从左往右扫,记录每个位置及其之前(的数量,从后往前扫,记录每个位置及其之后)的数量,再对每个位置枚举一次,求当前位置及之前(数量以及当前位置及其之后)数量的较小值,最后记录所有位置中该较小值的最大值,设其为x,依次输出前x个(的位置以及最后x个)的位置即可。
(正确性证明待补)
AC代码
#include
#include
#include
#include
#include
#include
#define MOD 1000000007
#include
using namespace std;
char s[10005];
int cot1[10005],cot2[10005];
int main()
{
scanf("%s",s+1);
int i;
for(i=1;s[i];i++)
{
cot1[i]=cot1[i-1]+(s[i]=='(');
}
i--;
for(;i;i--)
{
cot2[i]=cot2[i+1]+(s[i]==')');
}
int k=0;
for(i=1;s[i];i++)
{
k=max(k,min(cot1[i],cot2[i]));
}
int len=i-1;
if(k==0)
{
printf("0");
}else
{
printf("1\n");
printf("%d\n",2*k);
int temp=k;
for(i=1;temp&&s[i];i++)
if(s[i]=='(')printf("%d ",i),temp--;
temp=k;
stack<int>sta;
for(i=len;i&&temp;i--)
{
if(s[i]==')')sta.push(i),temp--;
}
while(!sta.empty())
{
printf("%d ",sta.top());sta.pop();
}
}
return 0;
}
C. Kuroni and Impossible Calculation
题意
给定n,m,求一个长为n的数组a[]中 ∏ 1 ≤ i < j ≤ n ∣ a i − a j ∣ ∏_{1≤i
题解
n>m时由抽屉原理知答案必为0。
n<=m时直接暴力算。
AC代码
#include
#include
#include
#include
#include
#include
#define MOD 1000000007
using namespace std;
long long ans[1005];
long long n,m;
int main()
{
scanf("%I64d%I64d",&n,&m);
if(n>m)printf("0");
else
{
for(long long i=1;i<=n;i++)scanf("%I64d",&ans[i]);
long long finalans=1;
for(long long i=1;i<n;i++)
for(long long j=i+1;j<=n;j++)
{
finalans*=(abs(ans[i]-ans[j])%m);
finalans%=m;
}
printf("%I64d",finalans);
}
return 0;
}
D. Kuroni and the Celebration
题意
这是个交互题,给定一个n,一棵n个结点树的n-1条边,允许最多进行n/2(向下取整)次询问,每次询问可以得知两个点的LCA,目标是找到这棵树的树根。
题解
(其实感觉挺乱搞的)每次搜树的直径,然后询问直径两个端点的LCA,然后将直径上LCA两边的点及它们的子树全部删除,重复直到剩下一个点。
(正确性证明待补)
AC代码
#include
#include
#include
#include
#include
#include
#define MOD 1000000007
#define N 10005
using namespace std;
int p[N],nxt[N],he[N],f[N],depth[N];
int cot,que_cot,ans,n,n_2;
int que[1005];
int flag[1005];
void addedge(int from,int to)
{
cot++;p[cot]=to;nxt[cot]=he[from];he[from]=cot;return;
}
void clearflag()
{
for(int i=1;i<=n;i++)if(flag[i]>0)flag[i]=0,depth[i]=0;return;
}
void dfs(int now)
{
flag[now]=1;
for(int i=he[now];i;i=nxt[i])
if(flag[p[i]]==0)
{
f[p[i]]=now;
depth[p[i]]=depth[now]+1;
dfs(p[i]);
}
return;
}
void findway()
{
clearflag();
dfs(ans);
int max=0,pos=0;
for(int i=1;i<=n;i++)
if(flag[i]>0&&depth[i]>max){max=depth[i];pos=i;}
clearflag();
f[pos]=0;
dfs(pos);
max=0;
que_cot=0;
for(int i=1;i<=n;i++)
if(flag[i]>0&&depth[i]>max){max=depth[i];pos=i;}
for(int i=pos;i;i=f[i])
{
que_cot++;que[que_cot]=i;
}
}
void ask()
{
cout<<"? "<<que[1]<<' '<<que[que_cot]<<endl;
cout.flush();
cin>>ans;
}
void set_it(int now)
{
flag[now]=-1;
n_2--;
for(int i=he[now];i;i=nxt[i])
if(flag[p[i]]>=0)
{
set_it(p[i]);
}
return;
}
void search_and_set()
{
int pos;
for(int i=1;i<=que_cot;i++)if(que[i]==ans)pos=i;
flag[ans]=-1;
if(pos>1)set_it(que[pos-1]);
if(pos<que_cot)set_it(que[pos+1]);
flag[ans]=0;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
addedge(x,y);addedge(y,x);
}
ans=1;
n_2=n;
while(n_2!=1)
{
findway();
ask();
search_and_set();
}
cout<<"! "<<ans<<endl;
cout.flush();
return 0;
}
E. Kuroni and the Score Distribution
题意
给定n,m,要求构造一个长为n的数组a[]有 1 ≤ a 1 < a 2 < ⋯ < a n ≤ 1 0 9 1≤a_1
题解
是个构造题,我没证明最大可构造的上限数所以没写出这题。看了tourist的代码之后大概懂了。
题解待补
AC代码
#include
#include
#include
#include
#include
#include
#define MOD 1000000007
const long long M=100000;
using namespace std;
long long n,m;
long long ans[10005],cot;
int main()
{
scanf("%I64d%I64d",&n,&m);
cot=n;
for(long long i=1;i<=n;i++)ans[i]=i*2-1;
long long mx=0;
for(long long i=1;i<=n;i++)mx+=(i-1)/2;
if(mx<m) printf("-1");
else
{
for(cot=n+1;(cot-n-1)/2<m;cot++)
{
ans[cot]=(cot-n)*M;m-=(cot-n-1)/2;
}
long long now=cot-n;
while((cot-n-1)/2>m)
{
m++;now+=2;
}
ans[cot]=now*M;
for(long long i=cot-n+1;i<=cot;i++)
{
printf("%I64d ",ans[i]);
}
}
return 0;
}