《HDU 2020 多校 第一场》

1005 :

Fibonacci Sum

从斐波那契的通项入手。

思路:

 

所以 $ans =  \sum_{i = 0}^{n} ans1^k = \sum_{i = 0}^{n} \frac{1}{T^k} (b^i-c^i)^k$

令$f[i] = (b^i-c^i)^k$

那么ans = $\frac{1}{T^k} * \sum_{i = 0}^{n} f[i]$

首先对f[i]二项式展开,然后求和合并之后。

可以发现$sum = C(k,0) *(-1)^k( (a^0)^0*(b^0)^k+(a^1)^0*(b^1)^k +....)+C(k,1)... $

对于C(k,i)里的每一项是一个等比数列的求和。

那么可以O(1)求出。最后枚举k去算总和即可

 由于这里常数过大,所以先预处理一下逆元。

同时由于n稍微大了些。

所以通过欧拉降幂公式,因为模数为质数。

a^b % p = a^(b % (p-1)) % p

然后因为C(k,i)之间公比是乘a/b倍的,所以不需要每次都快速幂求公比。

只需要前面的公比*a/b即可。

还有当公比为1时中间等比数列求和的分母为0,这时不用求和公式,直接可以发现其中每项都是1,那么求和就是n

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 1e5+5;
const LL Mod = 1e9+9;
#define pi acos(-1)
#define INF 1e8
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
LL a = 691504013,b = 308495997,d = 383008016;
LL f[N],inv[N];
inline LL read()
{
     LL x = 0,f = 1;char c = getchar();
     while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
     while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
     return x*f;
}
LL quick_mi(LL a,LL b)
{
     LL re = 1;
     a %= Mod;
     while(b)
     {
          if(b&1) re = (re*a)%Mod;
          a = (a*a)%Mod;
          b >>= 1;
     }
     return re;
}
void init()
{
     f[0] = 1;
     for(int i = 2;i < N;++i) f[i] = f[i-1]*i%Mod;
     inv[N-1] = quick_mi(f[N-1],Mod-2);
     for(int i = N-2;i >= 0;--i) inv[i] = inv[i+1]*(i+1)%Mod;
}
LL C(LL n,LL m)
{
     return f[n]*inv[m]%Mod*inv[n-m]%Mod;
}
LL slove(LL n,LL c,LL k)
{
     LL A = quick_mi(a,c%(Mod-1)),B = quick_mi(b,c%(Mod-1));
     LL aa = 1,bb = quick_mi(B,k),tmp = quick_mi(B,Mod-2);//预处理第一项公比
     LL ans = 0;
     for(LL i = 0;i <= k;++i)
     {
          LL x = aa*bb%Mod;//求出公比
          LL ma = C(k,i);
          LL sum = x*(quick_mi(x,n%(Mod-1))-1+Mod)%Mod*quick_mi(x-1,Mod-2)%Mod;//等比数列求和
          if(x == 1) sum = n%Mod;//公比为1时
          if((k-i) & 1) ans = (ans-ma*sum%Mod)%Mod;//-1是偶次还是幂次
          else ans = (ans+ma*sum%Mod)%Mod;
          aa = aa*A%Mod*tmp%Mod;//公比递推
     }
     LL ta = quick_mi(d,Mod-2);
     ans = ans*quick_mi(ta,k)%Mod;
     ans = (ans%Mod+Mod)%Mod;
     return ans;
}
int main()
{
     init();
     int t;t = read();
     while(t--)
     {
          LL n,c,k;
          n = read(),c = read(),k = read();
          LL ans = slove(n,c,k);
          printf("%lld\n",ans);
     }
   //  system("pause");
     return 0;
}
View Code

 

1009:

Leading Robots

思路:

有非常多的解法。

1:

我们知道x = x0+1/2 a*t*2.

那么以t^2为横坐标,x为纵坐标来建xoy坐标系。

那么先按x坐标来排序,之后我们从下往上扫,来判断每条直线是否可以成为领队,同时用一个单调栈来维护领队

当当前直线的a >= 栈顶直线的a时,显然在他右边的而且a还大于它,那么栈顶元素不可能成为领队,所以栈顶出栈。

否则判断当前直线与栈顶相遇 的时间是否  <= 栈顶元素和栈内栈下一个元素的相遇时间。如果是,那么显然在栈顶元素成为领队前就会被当前直线超到。那么栈顶出栈。

注意的是时间是t^2,然后用mp来维护一下重复的点,有重合那么该点不可能为领队。

2.形象理解。

将所有元素按加速度升序。同样单调栈来维护领队。

对于当前,那么显然之后的元素a 都 >= 栈顶。

如果这时当前元素的 x >= 栈顶元素。同样的栈顶出栈

那么只需要判断 当前元素遇到栈顶的时间是否 <= 栈顶 与栈内栈顶下一个相遇的时间。满足则出栈。

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 5e4+5;
const int Mod = 1e9+9;
#define pi acos(-1)
#define INF 1e8
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
struct Node{
     LL x,a;
     friend bool operator < (const Node &a,const Node &b) 
     {
          if(a.a == b.a) return a.x < b.x;
          return a.a < b.a;
     }
}f[N];
bool check(Node a,Node b,Node c)
{
     return (a.x-b.x)*(c.a-b.a)-(b.x-c.x)*(b.a-a.a) <= 0;
}
int q[N];
int main()
{
     int t;scanf("%d",&t);
     while(t--)
     {
          int n;scanf("%d",&n);
          map<Node,int> mp;
          for(int i = 1;i <= n;++i) 
          {
               scanf("%lld %lld",&f[i].x,&f[i].a);
               mp[f[i]]++;
          }
          sort(f+1,f+n+1);
          int cnt = 0;
          for(int i = 1;i <= n;++i)
          {
               while((cnt > 0 && f[i].x >= f[q[cnt]].x) || (cnt > 1 && check(f[i],f[q[cnt]],f[q[cnt-1]]))) cnt--;
               q[++cnt] = i;
          }
          int ans = 0;
          for(int i = 1;i <= cnt;++i)
          {
               if(mp[f[q[i]]] == 1) ans++;//这里是栈内的元素判重,少些了q调了好久
          }
          printf("%d\n",ans);
     }
     system("pause");
     return 0;
}

 

posted @ 2020-07-22 14:41  levill  阅读(354)  评论(0编辑  收藏  举报