题面node
在一场奇怪的梦里,小Y来到了一个神奇的国度。这个国度能够用一根数轴表示,小Y在\(N\)处,而小Y想吃的美食在\(K\)处。c++
小Y有两种方式移动,一种叫作步行,一种叫作瞬移。对于每次步行操做,小Y能够从\(x\)移动到\(x+1\)或者\(x-1\),而对于每次瞬移操做小Y能够从\(x\)瞬移到\(2x\)。那么小Y最少要移动多少次才能到达\(K\)处吃到食物呢?数据结构
【数据范围】\(0\le N,K\le 100,000\)优化
题解spa
水题。只须要bfs计算每一个点的最短路程便可。首先不可能走到负数点(必定不须要);其次不可能走到超过2e5的点(更多的必定会远离),所以能够肯定较紧的边界\([0,200000]\)。code
思考:4min 实现:10min;排序
预计100 实际:90ci
没看到小于等于,边界设定为了\(>0\),结果挂了第三个点(\(N=100000,K=0\))input
AC代码:it
#include<bits/stdc++.h> using namespace std; const int N=200009,INF=0x3f3f3f3f; typedef pair<int,int> P; int n,k,f[N]; bool v[N]; int main(){ freopen("meet.in","r",stdin); freopen("meet.out","w",stdout); scanf("%d%d",&n,&k); memset(f,INF,sizeof(f)); queue<P> que; que.push(make_pair(n,0)); while(!que.empty()){ P now=que.front(); que.pop(); int pos=now.first,val=now.second; //cout<<pos<<endl; v[pos]=true; f[pos]=min(f[pos],val); /*WA: pos-1>0*/ if(pos-1>=0&&pos-1<N&&!v[pos-1]) que.push(make_pair(pos-1,val+1)); if(pos+1>=0&&pos+1<N&&!v[pos+1]) que.push(make_pair(pos+1,val+1)); if(pos*2>=0&&pos*2<N&&!v[pos*2]) que.push(make_pair(pos*2,val+1)); } cout<<f[k]<<endl; return 0; }
题面
给定长度为\(n\)的序列\(a_1,\dots,a_n\),定义一次操做为:
给定整数\(k\),求对\(a\)进行\(k\)此操做后的序列,对\(10^9+7\)取模。
题解
Subtask:
1~8 暴力
1~20 矩阵快速幂+对称性优化
19~22 每次操做的系数在杨辉三角中右下移一格 组合数表示便可
正解:
操做后序列每一项都是由前\(i\)个数乘上系数之和,而系数正好就是\(a[i]=1\)中答案序列倒过来
所以只要在19~22上加权便可
若是直接每次算组合数会超时,因此须要用前一项来推有一项
看了5分钟以为应该就是考虑每一项对总答案的贡献系数,因此想到\(a_i\)是由\(a_1,a_2,\dots,a_i\)乘上系数起来的就能够了。实际作的时候发现这个系数很难求,当时想的是高阶等差数列,可是又没有求和公式,因此就不会作了
其实系数的规律已经发现了 只须要看到是组合数而不仅是高阶等差数列就A掉了)
最后写了个递推暴力 过了8个点(\(f[i][j]=f[i-1][j]+f[i][j-1]\))
还在想是否是须要优化这个递推过程
AC代码:
#include<bits/stdc++.h> using namespace std; const int N=5009,K=1009,P=1e9+7; typedef long long ll; ll n,k,a[N]; ll b[N],c[N]; //b记录答案,c记录系数 void input(){ scanf("%lld%lld",&n,&k); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); } ll qpow(ll x,ll y){ ll res=1,tmp=x; while(y){ if(y&1) res=(res*tmp)%P; tmp=(tmp*tmp)%P; y>>=1; } return res; } void solve(){ //for(int i=1;i<=n;i++) // c[i]=C(i-1,k+i-2); //原来的C(x,y)用于计算组合数,但会超时,所以改成递推 c[1]=1; for(int i=2;i<=n;i++) c[i]=(((c[i-1]*(k+i-2))%P)*qpow(i-1,P-2))%P; for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) b[i]=(b[i]+a[j]*c[i-j+1])%P; for(int i=1;i<=n;i++) printf("%d ",b[i]); } int main(){ freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); input(); /*if(k<=1000) solvedp(); else*/ solve(); return 0; }
题面
恋之微风·小乔,是手游《王者荣耀》中的法师型英雄,擅长远程消耗。小乔有一把神奇的扇子,借助灵活的走位能够对敌人形成高额的伤害。小乔是小 A 最喜欢(会玩)的英雄之一。在一场梦里,小 A 与小乔来到了一个异次元世界。
异次元世界位于极坐标系中。小乔定义了一个值\(m\),以等分\([-\pi,\pi]\)弧度。小乔利用她神奇的扇子,进行\(n\)次“绽开之舞“操做。对于第\(i\)次“绽 放之舞”操做,小乔将设定半径\(r_i\),起始位置\(s_i\),终止位置\(t_i\),她借助本身神奇 的扇子,以坐标系原点为圆心,\(r_i\)为半径,将圆心角\(\dfrac{\pi s_i}{m}\)到圆心角\(\dfrac{\pi t_i}{m}\)这部分扇形区域逆时针叠加一层“治愈微笑”。
小乔想到了一个有趣(奇怪)的问题,她但愿知道有多大面积的区域被叠加 过至少\(k\)层“治愈微笑”。这个问题难倒了平日里善于发现并解决问题的小 A,现 在小 A 求助于你,但愿你能帮他解决这个问题。
咱们设答案的值为\(T\),为了方便表达,你只须要输出\(T\cdot \dfrac{2m}{\pi}\)(能够证实这是 一个非负整数)的值便可。
题解
将扇形的起始边和结束边排序,将圆周分红\(O(n)\)个部分。考虑一个区间时,将覆盖此区间的全部扇形取出,求出第\(k\)大的扇形,其覆盖面积就是符合条件的面积(由于较大的扇形必定覆盖较小的梯形)。
支持查询第\(k\)大数并能够插入和删除的数据结构我选用的是BIT(平衡树也能够)
须要注意\(t_i\)可能小于\(s_i\)。
一开始想的是扫描线 可是想不清楚
而后就去写了暴力和差分的部分分 结果差分写挂了
订正的时候由于C++不知道什么诡异的断定机制调了很久
包括但不只限于node
(6行)里面的int
改为ll
就挂;在添加节点(35行)时若是不用tmp
就会断定错误等等等等)
后面发现是在改ll
的时候忘了把%d
改为%lld
了……
AC代码:
#include<bits/stdc++.h> using namespace std; const int N=200009; typedef long long ll; ll n,m,k,r[N],s[N],t[N],bit[N<<1]; struct node{ ll p,v,r; //pos,val(-1/1),radius bool operator < (const node &a)const{ return p<a.p; } } h[N<<1]; void input(){ cin>>n>>m>>k; for(ll i=1;i<=n;i++) scanf("%lld%lld%lld",&r[i],&s[i],&t[i]); } void upd(ll pos,ll val){ while(pos<=N){ bit[pos]+=val; pos+=(pos&-pos); } } ll query(ll pos){ ll res=0; while(pos){ res+=bit[pos]; pos-=(pos&-pos); } return res; } void solve(){ for(ll i=1;i<=n;i++) s[i]+=m+1,t[i]+=m+1; int tot=0; for(ll i=1;i<=n;i++){ int tmp=s[i]-t[i]; if(tmp<0){ h[++tot]=(node){s[i],1,r[i]}; h[++tot]=(node){t[i],-1,r[i]}; } else{ h[++tot]=(node){1,1,r[i]}; h[++tot]=(node){t[i],-1,r[i]}; h[++tot]=(node){s[i],1,r[i]}; h[++tot]=(node){2*m+1,-1,r[i]}; } } sort(h+1,h+tot+1); ll ans=0,cnt=0; for(ll i=1;i<=tot-1;i++){ upd(h[i].r,h[i].v); cnt+=h[i].v; if(cnt<k) continue; ll l=1,r=N-1; while(l!=r){ ll mid=(l+r)>>1; ll tmp=cnt-query(mid)+1; if(tmp>k) l=mid+1; else r=mid; } ans+=l*(h[i+1].p-h[i].p)*l; } cout<<ans<<endl; } int main(){ freopen("xiaoqiao.in","r",stdin); freopen("xiaoqiao.out","w",stdout); input(); /*if(n<=100) solveBF(); else solveT();*/ solve(); return 0; }