第一次写博客,记录一下cf的训练过程,以激励自己吧。在这之前消沉了很长一段时间,才发现和同龄人差距越来越大,如果努力都不努力,那谈何抱怨天赋能力呢?
A. Sasha and His Trip
简单的模拟题,思路对了即可。
我的思路是:因为越远油价越贵。所以先判断能否在一开始就把到达目的地的油加完,如果不行的话将油箱加满,之后每到一个城市加一次油。
#include<bits/stdc++.h>
using namespace std;
#define lld %I64d
#define REP(i,k,n) for(int i=k;i<n;i++)
#define REPP(i,k,n) for(int i=k;i<=n;i++)
#define mst(a,k) memset(a,k,sizeof(a))
#define LL long long
#define N 100005
#define mod 1000000007
#define INF 2147483646
int main()
{
int n,v;
scanf("%d %d",&n,&v);
if(n-1<=v)
printf("%d\n",n-1);
else
{
int num=n-v-1;
int ans=0;
REPP(i,1,num)
{
ans+=i+1;
}
printf("%d\n",ans+v);
}
}
B. Sasha and Magnetic Machines
依旧可以暴力模拟,一开始没有左右两个数字都遍历寻找,所以t了一次。实际上左侧的数字应该是数列中最小的数字收益最大。然后遍历寻找右侧数字以及x,以找到使总和变得最小的方案。
num=min(num,(x-1)*(mi-a[i]/x));
注意到数组里面的数字均小于100,还做了一些关于质数的剪枝,但实际上不写应该也没有影响。
#include<bits/stdc++.h>
using namespace std;
#define lld %I64d
#define REP(i,k,n) for(int i=k;i<n;i++)
#define REPP(i,k,n) for(int i=k;i<=n;i++)
#define mst(a,k) memset(a,k,sizeof(a))
#define LL long long
#define N 100005
#define mod 1000000007
#define INF 2147483646
inline int read(){int s=0;char ch=getchar();for(; ch<'0'||ch>'9'; ch=getchar());for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';return s;}
int a[N];
int flag[105];
int zhi[25]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
int main()
{
int n;
mst(flag,0);
REP(i,0,25)
{
flag[zhi[i]]=1;
}
scanf("%d",&n);
int mi=100,ma=0,sum=0;
REP(i,0,n)
{
scanf("%d",&a[i]);
sum+=a[i];
mi=min(mi,a[i]);
}
int x,num,ans=0;
REP(i,0,n)
{
if(flag[a[i]]==1)
continue;
x=0,num=0;
while(1)
{
x++;
if(a[i]%x)
continue;
if(mi*x>=a[i]/x)
{
num=min(num,(x-1)*(mi-a[i]/x));
break;
}
num=min(num,(x-1)*(mi-a[i]/x));
}
ans=min(ans,num);
}
printf("%d\n",sum+ans);
}
Γ(z)=∫0∞tz−1e−tdt .
\Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.
Γ(z)=∫0∞tz−1e−tdt.
C. Sasha and a Bit of Relax
这题知道结论思维正确的话很快就能解决(然而我没有QAQ)
这题有一个前提结论首先应该了解:
设前缀和数组pref(i)=a1⊕a2⊕…⊕ai. 那么al⊕al+1⊕…⊕ar=pref(r)⊕pref(l-1)。正常应该是自己都能推出来的,我后来问dalao才反应过来这一点。
这道题一开始我题目读错了,以为是mid左侧所有元素异或==mid右侧所有元素异或,以错误的思路做了一个小时。
实际上的做法:设xor[x,y]表示从x到y异或和。则xor[l,mid-1]==xor[mid,r]就可以转化为xor[l,r]==0。即求所有异或和为0的偶数长度子段。继续简化一下就是求pref(l-1)==pref®。
这样我们就可以利用一个区分奇偶数的前缀和桶结构来求出所有的funny pairs。
特别要注意的点是:例如2 2的样例会判错。原因是一开始时0 也在偶数位上出现了,需加入桶中。
详见代码:
#include<bits/stdc++.h>
using namespace std;
#define lld %I64d
#define REP(i,k,n) for(int i=k;i<n;i++)
#define REPP(i,k,n) for(int i=k;i<=n;i++)
#define mst(a,k) memset(a,k,sizeof(a))
#define LL long long
#define N 300005
#define mod 1000000007
#define INF 0x3f3f3f3f
inline int read(){int s=0;char ch=getchar();for(; ch<'0'||ch>'9'; ch=getchar());for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';return s;}
int a[N];
#define num (1<<20)+10
int odd[num],eve[num];//桶结构分开保存奇偶
int main()
{
LL ans=0;
int n=read();
a[0]=0;
REPP(i,1,n)
{
a[i]=read();
}
eve[0]++;
int pre=0;
REPP(i,1,n)
{
pre^=a[i];
if(i&1)
{
ans+=odd[pre];//加上在此之前这个前缀和出现的次数
odd[pre]++;
}
else
{
ans+=eve[pre];
eve[pre]++;
}
}
printf("%lld\n",ans);
}