Game with Integers
题目大意:v1和v2在玩游戏,玩家得到一个整数n,在轮到她的时候,可以对整数进行加1或者减1的操作,如果v1操作后,整数能够整除3,那么她就胜利了,如果10次移动后,v1还没有胜利,那么v2就胜利了。最后v1胜利就打印"First",否则打印"Second".
思路:能整除3即模3得0,一个数模上3只有三种情况,0,1,2;如果因为v1必须要操作,所以,实际上只要这个数n%3!=0,那么v1就会胜利,否则v2只需要复原v1的操作就能使v1每次都得对3的倍数操作,进而无法得到能整除3的数。
#include
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
if(n%3) printf("First\n");
else printf("Second\n");
}
}
250 Thousand Tons of TNT
题目大意:有排成一排的n个货物,可以选择每辆车装多少个,要求每辆车装的数量一样多,同时每辆车总和的最大值和最小值的差值最大。装箱顺序为,若选择每车装x个,那么1-x装在第一辆车,x+1-2x装在第二辆车……以此类推,求出最大差值。
思路:这道题,连续一段装在一辆车,且要求和,很容易想到前缀和,那么该如何选择一车装多少个呢?实际上暴力就可,不用担心会超时,那么嵌套循环的第二层不一定会跑。
#include
using namespace std;
#define int long long
int a[150010],sum[150010];
signed main()
{
int t;
scanf("%lld",&t);
while(t--)
{
int n;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
int ans=0;
for(int i=1;i<=n-1;i++)
{
if(n%i==0)
{
int mx=0,mi=150000000000000;
for(int j=i;j<=n;j+=i)
//1-i在一车
{
int d=sum[j]-sum[j-i];
mx=max(mx,d);
mi=min(mi,d);
}
ans =max(ans,mx-mi);
}
}
printf("%lld\n",ans);
}
}
Yarik and Array
题目大意:给定一个数组,要求出其非空子数组和的最大值,同时还要求非空子数组中的元素必须是奇偶相间。
思路:这个就是连续子序列求最大和的变式。累加,当遇到奇偶性不符合,或者加完得到负数的时候,重置即可。另外零对总和无贡献,但是会卡奇偶性,所以如果需要以0开头,那么尽量后跳一下,同样负数也是,所以尽量不以0和负数开头。
#include
using namespace std;
#define int long long
int a[200010];
signed main()
{
int t;
scanf("%lld",&t);
while(t--)
{
int n;
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
int k=1,mx=-1e9-7;;
//全部小于等于0
while(a[k]<=0&&k<=n) mx=max(mx,a[k]),k++;
if(k>n) printf("%lld\n",mx);
else if(k==n) printf("%lld\n",a[n]);
else
{
int sum=a[k],c=a[k],mx=a[k];//!!!a[k]后面可能全是小于它的数
for(int i=k+1;i<=n;i++)
{
if(c==-1e9-7)
{
sum=a[i];
mx=max(sum,mx);
c=a[i];
continue;
}
if((c%2==0&&a[i]%2)||(c%2&&a[i]%2==0))
{
sum += a[i];
if(sum<0)
{
k=i;
while(a[k]<=0&&k<=n) k++;
i=k-1;
sum=0;
c=-1e9-7;
}
c=a[i];
mx=max(mx,sum);
}
else
{
k=i;
while(a[k]<=0&&k<=n) k++;
i=k-1;
c=-1e9-7;
sum=0;
}
}
printf("%lld\n",mx);
}
}
}
Yarik and Musical Notes
题目大意:给定一个数组,数组里面的每个数ai表示的实际是2^ai,我们定义(a,b)是满足(2^a)^(2^b)=(2^b)^(2^a),问数组中有多少对ai,aj,满足i 思路: 所以,只有i,j,相等,或者一个为1,一个为2时才能满足。而题目给的i Queue Sort 题目大意:给定一个数组,我们可以进行若干次操作,每次操作将第一个数取出,放到末尾,然后去跟前面的比,如果前面的数大于它,那么就进行交换。问最少进行多少次操作可以是数组变成非递减的,如果不能使数组变成非递减的,那么就输出-1。 思路:这个题有点像冒泡排序,我们可以得到的结论就是,第一个数被取出放到后面,一定会放到一个对它来说有序的位置,或者换句话说,被操作过的数都会被放在有序的位置上,那么我们就要考虑,什么时候不能再进行操作了,很明显是最小的那个数为第一个数的时候,因为它还会被放回来,所以它后面的数也不能被操作。如果后面的数就是非递减的,那么自然无所谓,但是如果有递减存在,后面的数是无法被操作的,那么就无法使整个序列有序。所以我们只需要找到最小的数,去看它后面的数是否有递减存在即可。 Alex's whims 题目大意:现有一棵树,要求是第i天,树中要有两叶子节点的距离为di,我们可以进行的操作如下: 选择u,v1,v2,u和v1有边相连,u和v2没有边相连,我们可以将u与v2连起来,同时将u和v1之间的边断掉。现在要我们自己给出一棵树,并给出关于每个di需要如何操作,打印u,v1,v2,如果不需要操作那么就打印-1,-1,-1。只要每步操作合法即可。 思路:这道题看上去非常麻烦,既要我们自己给出一棵树,对每个di,我们还要来找是否已经有合法的点,如果没有该如何操作。但是实际上,有个特别简单的思路,即将n个节点顺次接起来,以1为根节点,我们现在相当于得到了支路1。每次的距离为d,即这条路上有有d+1个点。我们以根节点1作为一个固定的叶子节点,我们来讨论普遍的三种情况: 1.支路1上的点的数量恰好等于d+1,那么就不用进行任何操作,因为从1到叶子节点刚好可以满足要求。 2.支路1上点的数量多于d+1,我们可以将末尾多的点截下来接到支路2后面。(支路2最初为空,表示支路2的数组最初只有节点2,因为1要做叶子节点,所以不能接在1后面) 3.支路1上点的数量小于d+1,那么就将差的那部分从支路2的末尾截下来接到支路1的末尾。 这样就可以满足题目的要求了。#include
#include
#include