k小数查询
我就说题目描述中说到什么算法,就一定不会用到什么算法...果然在想清楚之前最好还是不要打代码,不然就是wrong,调,wrong,调...陷入死循环...考虑这个题,考虑x肯定是一个关键,先找到x的位置,那么左端点一定小于等于os(x的下标位置)。思考后发现小于x的数十分关键,并且我们要保证合法的区间中一定只有k-1个小于x的数。既然如此,我们就将所有小于x的数的下标放到一个数组里,枚举每个左端点,统计每个左端点对答案的贡献。对于每个左端点而言,首先必须保证右端点要大于等于os,其次这个区间里只能有k-1个比x小的数字。那我们直接在刚才存过的数组里面找当前k-1个数组的下标即可,并且可以直接根据下一个小于x的位置计算答案。....
//不等,不问,不犹豫,不回头.
#include<bits/stdc++.h>
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair<ll,int>
#define PII pair<int,int>
#define ull unsigned long long
#define put(x) printf("%d
",x)
#define putl(x) printf("%lld
",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=200010;
int n,k,a[N],x,b[N],num;
inline int read()
{
int x=0,ff=1;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*ff;
}
int main()
{
//freopen("1.in","r",stdin);
get(n);get(x);get(k);
int os;
rep(i,1,n)
{
get(a[i]);
if(a[i]==x) os=i;
}
int sum=0;
rep(i,1,n)
{
if(a[i]<x)
{
b[++num]=i;
if(i<os) sum++;
}
}
b[num+1]=n+1;
ll ans=0;
int dd=1;
rep(i,1,os)//枚举每一个左端点。
{
int ss=dd;//ss表示当前i这个点离得最近的小于x的下标在b中的下标。
if(sum<=k-1&&ss+k-2<=num)
{
ans+=b[ss+k-1]-max(b[ss+k-2],os);
}
if(i==b[dd]) dd++,sum--;
}
putl(ans);
return (0^_^0);
}
//以吾之血,铸吾最后的亡魂.
牛老板
好吧,我承认是我失去了勇气,没有继续思考下去...
考虑这个题,如果只用6和9的话,显然每个数都能转化成6进制数和9进制数,那么用的纸币的数量就是转化成的6进制数和9进制数下所有位数的和,考虑两个一起用的话,怎样会使答案更优,显然是某些数,在转化成9进制数时,其中某部分所有位数的和非常大,但用6进制的话就很简单了。如果这个不理解的话,可以这样想,每个数都可以写成若干个9的次幂相乘的形式,(当然了前面是有系数的但系数小于等于8),我们考虑如何用(6^i)使得答案更优,可能存在一些部分我们进行适当的拆解出来后,这一部分用(6^i)表示出来后系数和会更小,既然如此,我们直接考虑当前数的最高位的进制是9还是6,然后用递归的方式实现并且在两者之间取min即可。
//不等,不问,不犹豫,不回头.
#include<bits/stdc++.h>
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair<ll,int>
#define PII pair<int,int>
#define ull unsigned long long
#define put(x) printf("%d
",x)
#define putl(x) printf("%lld
",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
map<ll,int>f;
inline ll read()
{
ll x=0,ff=1;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*ff;
}
inline int find(ll n)
{
if(n<6) return n;
if(f.find(n)!=f.end()) return f[n];
ll s1=1,s2=1;
while(s1*6<=n) s1*=6;
while(s2*9<=n) s2*=9;
return f[n]=min(find(n-s1),find(n-s2))+1;
}
int main()
{
//freopen("1.in","r",stdin);
int get(T);
while(T--)
{
ll get(n);
putl(find(n));
}
return (0^_^0);
}
//以吾之血,铸吾最后的亡魂.
贪吃蛇
比遍体鳞伤更可怕的是内心的堕落....
考虑最后牛牛蛇的最大长度是多少?肯定是全部蛇的和啊,只要让一个蛇吃掉其他全部的蛇就可以了。那我们的目标就是每一次都尽可能增加这个全部蛇的和,考虑怎么样才能达到这个目的,由于复活的时间是固定的,我们可以将时间T分为(frac{T}{x}+1)这么多轮,每一轮可以进行蛇吃蛇的操作,显然的是由于蛇复活的长度不变,所以我们每轮都让蛇吃别人或被吃,这样的话下一轮复活后总增加后的长度最大。考虑怎么做,我们可以先将所有蛇的长度从小到大排序,我们向让次大的吃最大的,第三大的吃次大的,第四大的吃第三大的,...这样一直进行下去,这样能使最大的长度不断累计...最后最小的吃次小的,这样一轮之后,我们的蛇的长度由非严格递增变为非严格递减,之后我们再2号蛇吃1号蛇,3号蛇吃2号蛇,...最后n号蛇吃n-1号蛇,这样一直反复就行。发现这个递推可以用矩阵快速幂维护,那么总复杂度为(O(n^3logM)).
//不等,不问,不犹豫,不回头.
#include<bits/stdc++.h>
#define _ 0
#define ls p<<1
#define db double
#define rs p<<1|1
#define P 1000000007
#define ll long long
#define INF 1000000000
#define get(x) x=read()
#define PLI pair<ll,int>
#define PII pair<int,int>
#define ull unsigned long long
#define put(x) printf("%d
",x)
#define putl(x) printf("%lld
",x)
#define rep(x,y,z) for(int x=y;x<=z;++x)
#define fep(x,y,z) for(int x=y;x>=z;--x)
#define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
using namespace std;
const int N=55;
int n,x,M,l[N];
struct wy
{
ll a[N][N];
wy() {memset(a,0,sizeof(a));}
inline void clear(){memset(a,0,sizeof(a));}
wy friend operator*(wy a,wy b)
{
wy c;
rep(i,1,n) rep(j,1,n) rep(k,1,n) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%P;
return c;
}
wy friend operator^(wy a,ll y)
{
wy c;
rep(i,1,50) c.a[i][i]=1;
while(y)
{
if(y&1) c=c*a;
y>>=1;
a=a*a;
}
return c;
}
}A,B,C,D;
inline int read()
{
int x=0,ff=1;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*ff;
}
int main()
{
//freopen("1.in","r",stdin);
int get(T);
while(T--)
{
A.clear();B.clear();C.clear();D.clear();
get(n);get(x);get(M);
rep(i,1,n) get(l[i]);
sort(l+1,l+n+1);
rep(i,1,n) rep(j,1,i) A.a[i][j]=1;
rep(i,1,n) rep(j,i,n) B.a[i][j]=1;
rep(i,1,n) D.a[1][i]=l[i];
C=A*B;
int t=M/x+1;
C=C^(t/2);
if(t%2) C=C*A;
C=D*C;
if(t%2) put(C.a[1][1]);
else put(C.a[1][n]);
}
return (0^_^0);
}
//以吾之血,铸吾最后的亡魂.