题目:A. Magical Sticks
题意:在[1,n]范围内能最多能连接出多少根相同的棒子。
1和n-1相互连接,类推。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
if(n&1)
n=n/2+1;
else
n/=2;
printf("%d\n",n);
}
return 0;
}
题目:B. Magical Calendar
题意:一周的天数可为[1,k] (一行的格子数),在日历上连续涂色n天,并且每个格子都要有可以连接的,如过通过平移可以重叠则为1种情况。
我读的不是很清楚大致意思。
分情况讨论n>r时,1+2+…+r;
其余即1+2+3+…+n-1+1,画画图好理解。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll n,r;
scanf("%lld %lld",&n,&r);
ll temp;
if(n>r)
{
temp=r*(r+1)/2;
}
else
{
temp=n*(n-1)/2+1;
}
printf("%lld\n",temp);
}
return 0;
}
C. A Cookie for You
题意:a,b块香草和巧克力饼干,有两类客人按规律来吃,没得吃就生气,你可以安排来的顺序,问会不会导致生气(尽量不让生气)。
按照大类来看就是,第二类客人就吃少的饼干(相等就吃香草),第一类就吃多的(相等就吃巧克力),总的来说就是这样,(n+m>a+b)肯定失败,可知m<=min(a,b)时一定成功,第一类可以一直吃下去。当m>min(a,b)时,要平衡必须让第二类去吃多的,但是第一类客人把a,b吃的相等了再让第二类去吃多的那种,只能吃一次,代价是第一类去吃少的显然不行。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ll a,b,n,m;
scanf("%lld %lld %lld %lld",&a,&b,&n,&m);
if(n+m>a+b)
{
printf("No\n");
continue;
}
if(m<=min(a,b))
{
printf("Yes\n");
}
else
printf("No\n");
}
return 0;
}
题意:
找到1最多的行减最少的行的平方+同理列,这个值的最小值。
分析放的过程,先放1一个在左上角,对第一行贡献+1,第一列贡献+1,继续放就不能再放同一行同一列,这样就扩大了这一行或者这一列的贡献值,增大了结果。所以放下一行下一列,依次类推。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int a[310][310];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(a,0,sizeof(a));
int n,k,i,j;
scanf("%d %d",&n,&k);
if(k%n==0)
{
i=j=0;
int sum=0;
int hh=0;
while(sum<k)
{
a[(i)%n][(j+hh)%n]=1;
sum++;
i++;
j++;
if(sum%n==0)
{
hh++;
}
}
printf("0\n");
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d",a[i][j]);
}
printf("\n");
}
continue;
}
printf("2\n");
i=j=0;
int sum=0;
int hh=0;
while(sum<k)
{
a[(i)%n][(j+hh)%n]=1;
sum++;
i++;
j++;
if(sum%n==0)
{
hh++;
}
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d",a[i][j]);
}
printf("\n");
}
}
return 0;
}
题目:E1. Asterism (Easy Version)
题意:给定n个数的数组,表示怪物i有a[i]个糖果,你初始x个糖果,x>=a[i]则可以击败怪物并且糖果个数+1,f(x)为击败所有怪物的顺序方式的种类数,并且f(x)与p互质。输出可能的x,以及x的数量。
首先分析最小值显然是从小到大排列完依次打过去都可以赢。
我们sort数组,去枚举x的初始值,判断成功否,以及f(x)是否%p==0,存起来。f(x)怎么计算,小于x的个数是y的话,显然有y!,前y个的方式则为y!,a[y+1]大于x的时候,x要补充a[y+1]-x的值,那么f(x)=y!*(a[y+1]可以存在的位置的可能个数)即为前y+1个的情况,类推。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int a[2020];
int ans[2020];
int main()
{
int len=0;
int n,p,i,j;
scanf("%d %d",&n,&p);
int MAX=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
MAX=max(MAX,a[i]);
}
sort(a+1,a+1+n);
for(i=1;i<MAX;i++)
{
if(a[1]>i)
continue;
int temp=upper_bound(a+1,a+1+n,i)-a;
temp--;
if(temp>=p)
continue;
ll sum=1;
for(j=1;j<=temp;j++)
{
sum=(1ll*j*sum)%p;
}
if(!sum)
continue;
bool flag=true;
int hhu=i;
for(j=1;j<=n;j++)
{
if(hhu>=a[j])
{
hhu++;
continue;
}
else
{
flag=false;
break;
}
}
if(flag)
{
for(j=temp+1;j<=n;j++)
{
int tmp=a[j]-i;
sum=(1ll*(j-a[j]+i)*sum)%p;
}
if(!sum)
continue;
else
{
ans[++len]=i;
}
}
}
printf("%d\n",len);
for(i=1;i<=len;i++)
printf("%d ",ans[i]);
return 0;
}
题目:E2. Asterism (Hard Version)
题意和E1一样,n,p范围变了,到1e5。
分析x一定满足x+i-1>=a[i],我们找到这个下界枚举x>=(a[i]+1-i),f(x)是单调的,计算式子为sum=(1ll*(j-a[j]+x)*sum)%p,x变大sum变大,y!可能也变大,所以找到f(x)成立,f(x+1)不成立的临界点x,如果f(x)%p=0,那么f(x+1)也是%p=0的,那么就二分去找x的上界。
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
const int mod=998244353;
const int MAXlen=1e5+10;
long double eps=1e-9;
int a[100100];
int main()
{
int len=0;
int n,p,i,j;
scanf("%d %d",&n,&p);
int MAX=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
MAX=max(MAX,a[i]);
}
int MIN=0;
sort(a+1,a+1+n);
for(i=1;i<=n;i++)
{
MIN=max(MIN,a[i]-i+1);
}
int l=MIN,r=MAX;
int hh=-1;
int mid;
while(l<=r)
{
mid=(l+r)>>1;
int hhu=mid;
ll aa=1;
int sum=0;
bool flag=true;
if(a[1]>mid)
{
l=mid+1;
continue;
}
for(j=1;j<=n;j++)
{
if(hhu<a[j])
{
break;
}
else
sum++;
}
for(i=1;i<=sum;i++)
{
aa=(1ll*i*aa)%p;
}
for(;j<=n;j++)
{
int tmp=a[j]-hhu;
aa=(1ll*(j-a[j]+hhu)*aa)%p;
}
if(!aa)
{
hh=mid;
r=mid-1;
}
else
l=mid+1;
}
if(hh<=MIN)
{
printf("0\n");
return 0;
}
printf("%d\n",hh-MIN);
for(i=MIN;i<hh;i++)
{
printf("%d ",i);
}
return 0;
}