[关闭]
@wwwqeqeqeqe 2019-04-26T14:22:49.000000Z 字数 2048 阅读 678

Codeforces Round #549 (div.1)

codeforces

A The Beatles

题目大意:

给出一个圆,圆上一共有n*k个点,其中,在编号为k*t+1的点上有快餐店。现在有一个人一开始在编号为s的点,每次跑l km,当他再次跑回s时停止。但他忘记了s和l的值,只知道一开始距离最近的饭店的距离为a km,跑了一次(l km)后,离最近的饭店为b km。求最少跑步次数和最多跑步次数。

解题思路:

根据题目,我们可以知道,l所满足的条件分为:
l=i*k-a-b,l=i*k-a+b,l=i*k+a-b,l=i*k+a+b
我们枚举所有的l的情况,那么他们走的次数即为r=lcm(n*k,l)/l=n*k/gcd(n*k,l)。

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. ll gcd(ll x,ll y)
  5. {
  6. return y==0?x:gcd(y,x%y);
  7. }
  8. ll n,k;
  9. ll a,b;
  10. int main()
  11. {
  12. cin >> n >> k;
  13. cin >> a >> b;
  14. ll ansmx=0;
  15. ll ansmn=1e10;
  16. for(ll i=0;i<=n;i++)
  17. {
  18. ll l,r;
  19. l=i*k-a-b;
  20. if(l>0)
  21. {
  22. r=n*k/gcd(n*k,l);
  23. ansmx=max(ansmx,r);
  24. ansmn=min(ansmn,r);
  25. }
  26. l=i*k-a+b;
  27. if(l>0)
  28. {
  29. r=n*k/gcd(n*k,l);
  30. ansmx=max(ansmx,r);
  31. ansmn=min(ansmn,r);
  32. }
  33. l=i*k+a-b;
  34. if(l>0)
  35. {
  36. r=n*k/gcd(n*k,l);
  37. ansmx=max(ansmx,r);
  38. ansmn=min(ansmn,r);
  39. }
  40. l=i*k+a+b;
  41. if(l>0)
  42. {
  43. r=n*k/gcd(n*k,l);
  44. ansmx=max(ansmx,r);
  45. ansmn=min(ansmn,r);
  46. }
  47. }
  48. cout << ansmn << " " << ansmx << endl;
  49. return 0;
  50. }

B Lynyrd Skynyrd

题目大意:

给出一个长度为n的数组p和一个长度为m的数组a,对a进行q次查询,每次查询判断区间内,是否存在子序列恰好等于p的某个cyclic shifts。
cyclic shifts表示把p不断向左移动,移动出的的数放到右边。比如p为{2,1,3},那么,我们通过移动得到的数组就有{2,1,3},{1,3,2},{3,2,1}

解题思路:

我们首先找到离a[i]的最近上一个数字a[j]在什么位置,使得a[j]和a[i]恰好满足p[k-1]和p[k],我们把位置记为pre[i]。那么我们对每一个位置i进行这个查询,如果能找到,则在pre中记录离i最近的那个点。最后,通过log(n)次这样的操作,得到所有满足条件的情况。最后q次查询的时间复杂度为O(1)。    
            1      2     3       1       2       3
查询一次: -1      -1     1       2       3       4    pre[i] f[u][0]
查询二次: -1      -1    -1      -1      1       2    f[f[u][0]][0]   f[u][1]

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int MAXN = 2e5+7;
  5. const int INF = 0x3f3f3f3f;
  6. int f[MAXN][(int)log(MAXN)+5];
  7. int pre[MAXN];
  8. int p[MAXN],a[MAXN];
  9. int posa[MAXN],posp[MAXN];
  10. int ans[MAXN];
  11. int n,m,q,k;
  12. int findpre(int u){
  13. int t=n-1;
  14. while(t&&u){
  15. for(int i=k;i>=0;i--){
  16. if((1<<i)<=t){
  17. u=f[u][i];
  18. t-=(1<<i);
  19. break;
  20. }
  21. }
  22. }
  23. return u;
  24. }
  25. int main()
  26. {
  27. cin>>n>>m>>q;
  28. for(int i=1;i<=n;i++){
  29. cin>>p[i];
  30. posp[p[i]]=i;
  31. }
  32. for(int i=1;i<=m;i++){
  33. cin>>a[i];
  34. posa[a[i]]=i;
  35. }
  36. for(int pj,i=1;i<=m;i++){
  37. pj=(posp[a[i]]-1+n-1)%n+1;
  38. pre[i]=posa[p[pj]];
  39. posa[a[i]]=i;
  40. }
  41. for(int u=1;u<=m;u++){
  42. f[u][0]=pre[u]<u?pre[u]:0;
  43. }
  44. k=log(n)+1;
  45. for(int i=1;i<=k;i++){
  46. for(int u=1;u<=m;u++){
  47. f[u][i]=f[f[u][i-1]][i-1];
  48. }
  49. }
  50. for(int t,u=n;u<=m;u++){
  51. t=findpre(u);
  52. ans[u]=max(t,ans[u-1]);
  53. }
  54. for(int l,r,i=1;i<=q;i++){
  55. cin>>l>>r;
  56. if(ans[r]>=l)
  57. cout<<"1";
  58. else
  59. cout<<"0";
  60. }
  61. cout<<endl;
  62. return 0;
  63. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注