A. Magical Sticks
题意:给你n个数字,其中的数字可以随机组合,问可以组合形成最多同时几个数相等
题解:找规律即可,如果n为偶数,则有n/2个,反正(n+1)/2个
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
cout<<(n+1)/2<<endl;
}
return 0;
}
B. Magical Calendar
题意:有连续的n天,她可以选择任何满足1≤k≤r的整数k,并将k天设置为一周中的天数。如果日期到达一周的最后一天,则第二天的单元格是下一行(下方)中最左边的单元格。你可以选择从一周的任意一天开始,问有多少种不同的单元格形状。
题解:画图找规律可以发现,当k<n时的不同形状的单元格个数与选择的k值相同,即和为等差数列r(1+r)/2*,k>=n的部分形状平移之后形状都是一样的,所以只需要加1;
第一种情况r<n: 输出r(1+r)/2;
第二种情况r>=n:输出(n-1)(1+n-1)/2+1;**
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n,r;
cin>>n>>r;
if(n>r) cout<<r*1ll*(1+r)/2<<endl;
else cout<<1ll*(n-1)*(1+n-1)/2+1<<endl;
}
return 0;
}
C. A Cookie for You
题意:有两种曲奇,数量分别为a,b,有两类人个数为n(每一个人都会选择一个数目多的那种曲奇),m(每个人都会选择一个数目少的那种曲奇),如果a=b时可以随便选一个,问是否每个人都能够拿到任意一种类型的曲奇;
题解:如果(a+b)<(n+m)时肯定有人选不到,那么如果(a+b)>=(n+m) 的情况下我们只需要先考虑第二类人m(每个人都会选择一个数目少的那种曲奇)能否都能选到,如果a,b中的最小值大于等于m,则每个人都能选到,因为第一类人n(每一个人都会选择一个数目多的那种曲奇)能够在a=b的时候随便选一个,以此下去可以选到所有的数,所以不用考虑
#include<iostream>
#include<algorithm>
using namespace std;
long long int a,b,n,m,c;
int main()
{
int t;
cin>>t;
while(t--){
cin>>a>>b>>n>>m;
if((a+b)<(n+m)) cout<<"No"<<endl;
//第一种情况
else{
a=min(a,b);
if(a>=m) cout<<"Yes\n";
//找到最小值满足m个人需求即可
else cout<<"No\n";
}
}
return 0;
}
Problem D - Grid-00100
题解:当k能被n整除时,是可以使得每一行每一列个数相同的,如果有余数的话,把余数错开放在每行后面一个1,可以使得满足1+1=2 的情况的。
就这样构造:
上代码吧
#include<bits/stdc++.h>
using namespace std;
const int maxn=305;
int n,k,t;
int a[maxn][maxn];
int main () {
scanf("%d",&t);
while (t--) {
scanf("%d%d",&n,&k);
if (k%n==0) printf("0\n");
else printf("2\n");
int tt=0;
memset(a,0,sizeof(a));
for (int i=1;i<=k/n;i++) {
for (int j=0;j<n;j++) a[j][(j+tt)%n]=1;
tt++;
//先每行错开放k/n个,保f(A)=0;
}
if (k%n) for (int i=0;i<k%n;i++) a[i][(i+tt)%n]=1;
//再将剩余的1错开放在前k%n行中。
for (int i=0;i<n;i++) {
for (int j=0;j<n;j++) printf("%d",a[i][j]);
printf("\n");
}
}
return 0;
}
1371E1 - Asterism (Easy Version)
题解:让我们来定义m=max(a1,a2,…,an).
玉祖至少应该m−n+1糖果最初是为了赢得所有决斗,然后f(x)=0为x<m−n+1。这可以被p.
如果五十铃有相等的或更多的.m糖果一开始,任何排列都是有效的,然后f(x)=n!为x≥m。这可以被p也是。(因为p≤n)
然后,在这个子任务中,您应该找到每个f(x)可被p为m−n+1≤x<m在……里面O(n).
您可以找到f(x)通过以下模拟:
首先,让v={他们的敌人数量严格地少于x糖果),ans=1.
然后执行以下步骤i=x,x+1,…,x+(n−1).
v=v+{他们有多少敌人i糖果)
ans=ans∗v
v=v−1
现在,p是个质数。然后,“是否f(x)可被p“是”是否p乘成ans如v至少有一次。“
这可以在O(n)每个人的时间x.
总复杂性:O(n2)
#include<stdio.h>
int max(int a,int b){if(a>b){return a;}return b;}
int main(){
int n,p;
int st,fi;
int a[131072],bk[262144]={0},bas=0,i,j;
int res[131072],rc=0;
scanf("%d%d",&n,&p);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
bas=max(a[i],bas);
}
for(i=0;i<n;i++){bk[max(0,a[i]-bas+n)]++;}
for(i=1;i<262144;i++){bk[i]+=bk[i-1];}
for(i=0;i<=n;i++){
for(j=0;j<n;j++){
if((bk[i+j]-j)<=0){break;}
if((bk[i+j]-j)%p==0){break;}
if(j==n-1){res[rc]=i+(bas-n);rc++;}
}
}
printf("%d\n",rc);
for(i=0;i<rc;i++){
if(i){printf(" ");}
printf("%d",res[i]);
}printf("\n");
}
1371E2 - Asterism (Hard Version)
题解:
#include<stdio.h>
int max(int a,int b){if(a>b){return a;}return b;}
int main(){
int n,p;
int st,fi;
int a[131072],bk[262144]={0},bas=0,i;
scanf("%d%d",&n,&p);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
bas=max(a[i],bas);
}
for(i=0;i<n;i++){bk[max(0,a[i]-bas+n)]++;}
for(i=1;i<262144;i++){bk[i]+=bk[i-1];}
st=1;
for(i=1;i<=n;i++){
while(bk[st+(i-1)]<i){st++;}
}
st+=(bas-n);
fi=n;
for(i=1;i<=n;i++){
while(fi>0){
if(bk[fi+(i-1)]-(i-1)<p){break;}
fi--;
}
}
fi+=(bas-n);
if(st>fi){
printf("0\n\n");
return 0;
}
printf("%d\n",fi-st+1);
for(i=st;i<=fi;i++){
if(i!=st){printf(" ");}
printf("%d",i);
}printf("\n");
return 0;
}