0716 - 2018CCPC吉林赛区(重现赛)

2019-07-20  本文已影响0人  Celia_QAQ

题目地址:http://acm.hdu.edu.cn/contests/contest_show.php?cid=867

目录

| 1001 | The Fool | 39.75%(535/1346) |
| 1002 | The World | 24.87%(389/1564) |
| 1003 | Justice | 21.33%(202/947) |
| 1004 | The Moon | 36.57%(132/361) |
| 1005 | The Tower | 20.99%(115/548) |
| 1006 | The Hermit | 63.99%(183/286) |
| 1007 | High Priestess | 0.00%(0/1) |
| 1008 | Lovers | 34.04%(16/47) |
| 1009 | Strength | 83.87%(156/186) |
| 1010 | Wheel of Fortune | 100.00%(4/4) |
| 1011 | The Magician | 0.00%(0/14) |
| 1012 | The Hanged Man | 50.00%(1/2) |

附上题意分析的代码:https://blog.csdn.net/weixin_38686780/article/details/82846796
补题情况:除1007 1010 1011 1012 待续~

1001 - The Fool

题目描述

The Fool is numbered 0 the number of unlimited potential -and therefore does not have a specific place in the sequence of the Tarot cards . The Fool can be placed either at the beginning of the Marjor Arcam or at the end. The Major Arcana is often considered as the Fool's journey through life and as such, he is ever present and therefore needs no number.

Given n∈N+, print the parity of



输入

The first line of the input contains one integer T≤100, denoting the number of testcases. Then T testcases follow.
In each of the T testcases, there is a positive number n≤109

输出

For each testcase, print a single line starting with “Case i:”( i indicates the case number) and then "even" or “odd’', separated with a single space.

样例输入
3
1
10000
100000000
样例输出

Case 1: odd
Case 2: even
Case 3: even

参考:https://blog.csdn.net/birdmanqin/article/details/89789424
(打一下表,很容易就看出来,前3个都为奇,接着5个都为偶,接着7个都为奇,接着9个都为偶,...。很明显为一个首项为3,公差为2的等差数列。我们可以利用等差数列的求和公式,设出方程为(3+2k+1)k/2=n,我们可以利用一元二次方程求解公式得到k=ceil(sqrt(1.0+n)-1.0)。(这里向上取整是因为如果n不是恰好前k项的和,那么给出的n肯定属于下一项。)根据规律,若k为奇数,则为odd;若k为偶数,则为even。)
https://blog.csdn.net/yopilipala/article/details/96429963:其实这个题就是把商为1、2、3..... 1、2、3.....1、2、3.....的部分用O(1) O(1)O(1)复杂度找出来,然后求和就行了,打个表看了一下复杂度大概是2∗sqrt(n) 2*sqrt(n)2∗sqrt(n)。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll add(ll n) {
    ll Sum = 0;
    int cnt = 1;
    for(int pos1=1, pos2;pos1<=n;pos1 = pos2+1){//一段一段的找出来
        pos2 = n/(n/pos1);
        Sum += (pos2-pos1+1)*(n/pos1);
//        printf("%d %d %d\n",cnt++, pos2, pos1); 打表看复杂度的
    }
    return Sum;
}

int main() {
    freopen("1.in.txt", "r", stdin);
    int t; scanf("%d", &t);
    int T = t;
    while(t--) {
        ll n; scanf("%lld", &n);
        ll sum = add(n);
        string ans;
        if(sum&1) ans = "odd";
        else ans = "even";
        printf("Case %d: %s\n", T-t, ans.c_str());
    }
    return 0;
}

1002 - World

参考:(直接模拟过)
https://www.cnblogs.com/llke/p/10825213.html
https://blog.csdn.net/weixin_33836223/article/details/93499258

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define scac(x) scanf("%c",&x)
#define sca(x) scanf("%d",&x)
#define sca2(x,y) scanf("%d%d",&x,&y)
#define sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define scl(x) scanf("%lld",&x)
#define scl2(x,y) scanf("%lld%lld",&x,&y)
#define scl3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scs(x) scanf("%s",x);
#define pri(x) printf("%d\n",x)
#define pri2(x,y) printf("%d %d\n",x,y)
#define pri3(x,y,z) printf("%d %d %d\n",x,y,z)
#define prl(x) printf("%lld\n",x)
#define prl2(x,y) printf("%lld %lld\n",x,y)
#define prl3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prs(x) printf("%s",(x));
#define ll long long
#define LL long long
#define read read()
#define pb push_back
#define mp make_pair
#define P pair<int,int>
#define PLL pair<ll,ll>
#define PI acos(1.0)
#define eps 1e-6
#define inf 1e17
#define INF 0x3f3f3f3f
#define N 205
const int maxn = 1e5+5;
char d[3][100] = {"Yesterday","Today","Tomorrow"};
char city[4] = {'B','W','L','M'};
int ti[4] = {8,-5,0,3};
map<char,int> p;
int t,hh,mm;
char am[2],c1[100],c2[100],day[100];
int kase = 0;
int main()
{
    rep(i,0,4)
      p[city[i]] = ti[i];
    sca(t);
    while(t--)
    {
      scanf("%d:%d",&hh,&mm);
      scs(am);
      getchar();
      scs(c1);
      scs(c2);
      if(hh==12 && am[0] =='A')
        hh = 0;
      if(hh<12&&am[0] =='P')
        hh+=12;
      hh += p[c2[0]] - p[c1[0]];
 
      if(hh < 0)
      {
          strcpy(day,d[0]);
          hh += 24;
      }
      else if(hh < 24)
      {
          strcpy(day,d[1]);
      }
      else
      {
        strcpy(day,d[2]);
        hh-=24;
      }
      if(hh==0)
      {
        hh = 12;
        am[0] = 'A';
      }
      else if(hh > 0 && hh < 12)
      {
        am[0] = 'A';
      }
      else if(hh==12)
      {
        am[0] = 'P';
      }
      else
      {
        hh -= 12;
        am[0] = 'P';
      }
      printf("Case %d: %s %d:%02d %s\n",++kase,day,hh,mm,am);
    }
}

1003 - Justice


Sample Input
3
3
2 2 2
3
2 2 1
2
1 1

Sample Output
Case 1: NO
Case 2: YES
001
Case 3: YES
10

参考:https://blog.csdn.net/weixin_38686780/article/details/82846796#_108
利用二进制的原理,优先队列+并查集,先取出权值最小的,进行合并,如果两个值相同,则可以合并成一个k-1,最后判断是否有两个或两个以上的1出现即可

#include <bits/stdc++.h>
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define Pb push_back
#define  FI first
#define  SE second
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define IOS ios::sync_with_stdio(false)
#define DEBUG cout<<endl<<"DEBUG"<<endl; 
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int    prime = 999983;
const int    INF = 0x7FFFFFFF;
const LL     INFF =0x7FFFFFFFFFFFFFFF;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-6;
const LL     mod = 1e9 + 7;
LL qpow(LL a,LL b){LL s=1;while(b>0){if(b&1)s=s*a%mod;a=a*a%mod;b>>=1;}return s;}
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
int dr[2][4] = {1,-1,0,0,0,0,-1,1};
typedef pair<int,int> P;
const int maxn = 1e5+10;
int a[maxn];
int F[maxn];
int Find(int x){
   return x == F[x]?x:F[x] = Find(F[x]);
}
int main(void)
{
  int T;cin>>T;
  int kase =0;
  while(T--){
    
    int n;cin>>n;

    for(int i = 1;i <= n; ++i)
        F[i] = i;
    for(int i = 1;i <= n; ++i)
        scanf("%d",&a[i]);
    priority_queue<P>Q;
    for(int i = 1;i <= n; ++i)
        Q.push(P(a[i],i));

    while(!Q.empty()&&Q.top().first > 1){
        P p = Q.top(); Q.pop();
        if(p.first != Q.top().first){
            continue;
        }
        if(Q.empty()) break;
        P p2 = Q.top();Q.pop();
        int x = Find(p.second);
        int y = Find(p2.second);
        if(x < y)
            swap(x,y);
        F[x] = y;
        Q.push(P(p.first-1,y));
    }
    printf("Case %d: ",++kase);
    if(Q.size() < 2)
        puts("NO");
    else{
        puts("YES");
        for(int i = 1;i <= n; ++i){
            int x = Find(i);
            printf("%c",x == Q.top().second?'1':'0');
        }
        puts("");
    }
  }    

  return 0;
}

1004 - The Moon

Problem Description

The Moon card shows a large, full moon in the night’s sky, positioned between two large towers. The Moon is a symbol of intuition, dreams, and the unconscious. The light of the moon is dim, compared to the sun, and only vaguely illuminates the path to higher consciousness which winds between the two towers.

Sample Input

2
50
100

Sample Output

Case 1: 12.9933758002
Case 2: 8.5431270393

思路:https://blog.csdn.net/yopilipala/article/details/96449300:期望dp

所以一共有两种代码(记忆化(dfs)和dp写法)

#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
#define LL long long
#define eps 1e-6
#define inf 1e17
#define INF 0x3f3f3f3f
#define N 205
const int maxn = 1e5+100;
double  a[maxn],b[maxn];
double dp[maxn];
int p,n;
double pp;

double dfs(int q){
    if(q>200) q = 200;
    double qq = double(q)/200;
    if(q == 200)  return dp[q]=double(100)/p;
    if(dp[q] > -1)return dp[q];

    return dp[q]=double(1)+pp*(1-qq)*dfs(q+4) + (1-pp)*dfs(q+3);
}
int main(){
    ll t,n,m;
    scanf("%lld",&t);
    for(int i=1;i<=t;){
        int ans=0;
        //memset(dp,-1,sizeof(dp));
        scanf("%d",&p);
        pp=double(p)/100;
        printf("Case %d: %.10f\n",i++,dfs(4));
    }
    return 0;
}

用期望dp[i]的方法:

#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
#define LL long long
#define eps 1e-6
#define inf 1e17
#define INF 0x3f3f3f3f
#define N 205
const int maxn = 500;
double  a[maxn],b[maxn];
double dp[maxn];
int p,n;
double pp,q;

int main(){
    ll t,n,m;
    scanf("%lld",&t);

    for(int k=1;k<=t;){
    memset(dp,0.0,sizeof(dp));
    scanf("%d",&p);
    double pp = double(p)/100.0;
    dp[200]=double(1)/pp;
    for(int i=199;i>=0;i--){
        double qq=double(i)/200;
        dp[i]=pp*(qq+(1.0-qq)*(1.0+dp[min(200,i+4)]));
        dp[i]+=(1.0-pp)*(1.0+dp[min(200,i+3)]);
    }
        printf("Case %d: %.10f\n",k++,dp[4]);
    }
    return 0;
}

1005 - The Tower

输入输出:
Sample Input
2
1 2
1 1 1
-1.5 -1.5 -0.5
1 1
1 1 1
-1 -1 -1
Sample Output
Case 1: 0.3855293381
Case 2: 0.5857864376



参考:https://blog.csdn.net/weixin_38686780/article/details/82846796

代码:

#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
#define LL long long
#define eps 1e-6
#define inf 1e17
#define INF 0x3f3f3f3f
#define N 205
const int maxn = 500;
double  a[maxn],b[maxn];
double dp[maxn];
int p,n;
double pp,q;

int main(){
    ll t,n,m;
    double x0,y0,z0;
    double vx,vy,vz;
    double r,h;
    scanf("%lld",&t);
    int count;
    while(t--){
        scanf("%lf%lf",&r,&h);
        scanf("%lf%lf%lf",&x0,&y0,&z0);
        scanf("%lf%lf%lf",&vx,&vy,&vz);

        double A = (vx*vx + vy*vy)*h*h - vz*vz*r*r;
        double B = h*h*(2*y0*vy + 2*x0*vx) + (2*vz*h - 2*z0*vz)*r*r;
        double C = -r*r*(z0*z0 - 2*z0*h + h*h) + h*h*(x0*x0 + y0*y0);
                    
        double m=sqrt(B*B-4*A*C);
        double x1=(-B+m)/(2*A);
        double x2=(-B-m)/(2*A);

        if(x1>x2)swap(x1,x2);
        printf("Case %d: ",++count);
        if(x1<0) printf("%.10lf",x2);
        else {
            double z=z0+vz*x1;///x1所走过的高度(特殊情况)
            if(z>h||z<0)printf("%.10lf",x2);
            else printf("%.10lf",x1);
        }
        printf("\n");
    }
    return 0;
}

1006 - The Hermit


Sample Input
2
7
1 2 3 4 3 2 1
10
1 1 2 3 4 4 3 2 2 1

输入输出
Sample Output
Case 1: 2
Case 2: 0
Hint
In the first testcase of the example, the number of stations that can receive the perfect signal from each station i is respectively 0, 0, 1, 2, 1, 0, 0 in order, so the answer must be

0 xor 0 xor 1 xor 2 xor 1 xor 0 xor 0 = 2

参考:https://blog.csdn.net/aiyouyou_/article/details/89790003
题目所需要的条件

  1. k<i
  2. i覆盖k
  3. 存在电台j满足
    3.1 k<=j<i
    3.2 j到k的距离>=i到j的距离
    3.3 j覆盖k
    我们让j=i-1,那么,对于 <=k<=i-2(自然满足1 2 3.1) 的电台,
    有j-k=(i-1)-k>=1,i-j=i-(i-1)=1(所以满足3.2)
    因为对所有的 i 满足 (这就说明如果k<i,i覆盖k,那么对任意k<=j<=i,满足j覆盖k)
    所以3.3也满足。
    至于i本身和i-1,显然都不能完美接收i的信号。
    所以 = i左边覆盖的电台数-2
    对求异或和就ok啦。
#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
#define LL long long
#define eps 1e-6
#define inf 1e17
#define INF 0x3f3f3f3f
#define N 205
const int maxn = 500;
int  a[maxn],b[maxn];
//int dp[maxn];
int p,n;
double pp,q;

int main(){
    ll t,n,m;
    scanf("%d",&t);
    int count=0;
    while(t--){
        ll ans=0;
        scanf("%lld",&n);
        for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(a[i]>2)
        ans^=(a[i]-2);//讲真这种方法我也不知道能不能过。。。。
        }
        //if(ans<0)ans=0;
        printf("Case %d: %d\n",++count,ans);
    }

    return 0;
}


1008 - Lovers

Sample Input
2
3 2
wrap 1 3 1
query 1 2
4 4
wrap 1 3 0
wrap 2 4 3
query 1 4
query 2 3

Sample Output
Case 1:
22
Case 2:
6039
6006
Hint
1 ≤ T ≤ 5, 1 ≤ n, m ≤ 1e5, 1 ≤ l ≤ r ≤ n.

题意:
修改:将l,r 的所有字符串执行修改,在前后都加一个字符
查询:查询l,r 的和
分析:
我们发现这个修改操作满足可加行,两次修改可以合并成一个,类似区间加,用线段树维护以下value:

sum[o] sum[o]sum[o] 代表区间[l,r] [l,r][l,r]的和
k10 k10k10 代表 k10=∑i∈[l,r]

参考:https://blog.csdn.net/weixin_38686780/article/details/82846796
修改可以看做分解
addleft=左边加的部分 addleft = 左边加的部分addleft=左边加的部分
addright=右边加的部分 addright = 右边加的部分addright=右边加的部分
addlen=加入字符串的个数 addlen = 加入字符串的个数addlen=加入字符串的个数
然后按照相应规则进行更新
例如:只加入一个字符
题意:
修改:将l,r 的所有字符串执行修改,在前后都加一个字符
查询:查询l,r 的和
分析:
我们发现这个修改操作满足可加行,两次修改可以合并成一个,类似区间加,用线段树维护
https://blog.csdn.net/weixin_38686780/article/details/82846796#_108

例如:只加入一个字符

        tree[o].addleft     = (v * pow10[tree[o].addlen] + tree[o].addleft) % mod;
        tree[o].addright    = (tree[o].addright * 10 + v) % mod;
        tree[o].addlen      += 1;
        tree[o].sum = ( tree[o].sum * 10 + tree[o].k10 * v%mod * 10 + v * (r - l + 1)) % mod;
        // cout << tree[o].sum << endl;
        tree[o].k10 = (tree[o].k10 * 100) % mod;

https://blog.csdn.net/weixin_38686780/article/details/82846796#_108

#include <bits/stdc++.h>
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define Pb push_back
#define  FI first
#define  SE second
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define IOS ios::sync_with_stdio(false)
#define DEBUG cout<<endl<<"DEBUG"<<endl;
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int    prime = 999983;
// const int    INF = 0x7FFFFFFF;
const LL     INFF = 0x7FFFFFFFFFFFFFFF;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-6;
const LL     mod = 1e9 + 7;
LL qpow(LL a, LL b) {LL s = 1; while (b > 0) {if (b & 1)s = s * a % mod; a = a * a % mod; b >>= 1;} return s;}
LL gcd(LL a, LL b) {return b ? gcd(b, a % b) : a;}
int dr[2][4] = {1, -1, 0, 0, 0, 0, -1, 1};
typedef pair<int, int> P;
#define lson (o << 1)
#define rson (o << 1|1)
const int maxn = 1e5 + 10;
const int INF = 1e9;
typedef long long LL;
LL pow10[maxn * 3];
struct Tree {
    LL sum, k10, addleft, addright, addlen;
    int l, r;
};
Tree tree[maxn << 2];
void pushup(int o, int l, int r) {
    tree[o].sum = (tree[lson].sum + tree[rson].sum) % mod;
    tree[o].k10 =  (tree[lson].k10 + tree[rson].k10) % mod;
}
void Add(Tree &b, Tree &a) {
    b.sum = ( b.sum * pow10[ a.addlen] + a.addleft * b.k10%mod * pow10[a.addlen] + a.addright * (b.r - b.l + 1)) % mod;
    b.k10 = (b.k10 * pow10[2 * a.addlen]) % mod;

    b.addleft = (b.addleft + a.addleft * pow10[b.addlen]) % mod;
    b.addright = (b.addright * pow10[a.addlen] + a.addright) % mod;
    b.addlen = b.addlen + a.addlen;
}

void pushdown(int o, int l, int r) {
    if (tree[o].addlen > 0) {
        Add(tree[lson], tree[o]);
        Add(tree[rson], tree[o]);
        tree[o].addlen = tree[o].addright = tree[o].addleft = 0;
    }
}
void up(Tree & a, Tree b) {
    a.sum = (a.sum + b.sum) % mod;
}
void build(int o, int l, int r) {
    tree[o].l = l;
    tree[o].r = r;
    // cout<<l<<" "<<r<<endl;
    // tree[o].add = 0;
    tree[o].k10 = (r - l + 1);
    if (l == r)
    {
        tree[o].sum = tree[o].addright = tree[o].addleft = tree[o].addlen = 0;
        // cout<<l <<" "<<a[l]<<endl;
    }
    else {
        int m = (l + r) >> 1;
        build(lson, l, m);
        build(rson, m + 1, r);
    }
}
void Update(int o, int l, int r, int L, int R, int v) {
    // cout << tree[o].k10 << endl;
    if (L <= l && R >= r) {
        tree[o].addleft     = (v * pow10[tree[o].addlen] + tree[o].addleft) % mod;
        tree[o].addright    = (tree[o].addright * 10 + v) % mod;
        tree[o].addlen      += 1;

        tree[o].sum = ( tree[o].sum * 10 + tree[o].k10 * v%mod * 10 + v * (r - l + 1)) % mod;
        // cout << tree[o].sum << endl;
        tree[o].k10 = (tree[o].k10 * 100) % mod;
        return ;
    }
    pushdown(o, l, r);
    int m = (l + r) / 2;
    if (L <= m)
        Update(lson, l, m, L, R, v);
    if (R > m)
        Update(rson, m + 1, r, L, R, v);
    pushup(o, l, r);
}
Tree Query(int o, int l, int r, int L, int R) {

    if (L <= l && R >= r)
    {
        return tree[o];
    }
    Tree tmp;
    tmp.sum = 0;
    pushdown(o, l, r);
    int m = (l + r) >> 1;
    if (L <= m)
        up(tmp, Query(lson, l, m, L, R));
    if (R > m)
        up(tmp, Query(rson, m + 1, r, L, R));
    // cout<<tmp.sum<<endl;
    return tmp;
}
int n, m;
// char
int main(void) {
    pow10[0] = 1;
    for (int i = 1; i < maxn * 3; ++i)
        pow10[i] = pow10[i - 1] * 10 % mod;
    // cout << pow10[2] << endl;
    int T; cin >> T;
    int kase = 0;
    while (T--) {
        printf("Case %d:\n", ++kase);
        cin >> n >> m;
        me(tree);
        build(1, 1, n);
        while (m--) {
            char op[10];
            int l, r, d;
            scanf("%s%d%d", op, &l, &r);
            if (op[0] == 'w') {
                scanf("%d", &d);
                Update(1, 1, n, l, r, d);
            }
            else {
                printf("%lld\n", Query(1, 1, n, l, r).sum);
            }
        }
    }


    return 0;
}

/*

2
3 4
wrap 1 1 1
wrap 1 2 1
wrap 1 3 1
query 1 3


2
4 4
wrap 1 3 0
wrap 2 4 3
query 1 4
query 2 3

*/

上一篇下一篇

猜你喜欢

热点阅读