codeforces 145E Lucky Queries

本文介绍 CodeForces 145E 题目 Lucky Queries 的解题思路与代码实现,重点讲解如何快速判断幸运数,并通过树状数组进行区间加法及查询操作。
codeforces 145E  Lucky Queries
Time Limit:4000MS    Memory Limit:262144KB     64bit IO Format:%I64d & %I64u
Description

Petya loves lucky numbers. Everybody knows that lucky numbers are positive integers whose decimal representation contains only the lucky digits4 and 7. For example, numbers47, 744,4 are lucky and 5, 17, 467 are not.

Petya has an array consisting of n numbers. He wants to perform m operations of two types:

  • add lrd — add an integerd to all elements whose indexes belong to the interval froml to r, inclusive(1 ≤ l ≤ r ≤ n, 1 ≤ d ≤ 104);
  • count lr — find and print on the screen how many lucky numbers there are among elements with indexes that belong to the interval froml to r inclusive(1 ≤ l ≤ r ≤ n). Each lucky number should be counted as many times as it appears in the interval.

Petya has a list of all operations. The operations are such that after all additions the array won't have numbers that would exceed104. Help Petya write a program that would perform these operations.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 105) — the number of numbers in the array and the number of operations correspondingly. The second line contains n positive integers, none of which exceeds104 — those are the array numbers. Nextm lines contain operations, one per line. They correspond to the description given in the statement.

It is guaranteed that after all operations are fulfilled each number in the array will not exceed104.

Output

For each operation of the second type print the single number on the single line — the number of lucky numbers in the corresponding interval.

Sample Input

Input
3 6
2 3 4
count 1 3
count 1 2
add 1 3 2
count 1 3
add 2 3 3
count 1 3

Output
1
0
1
1
Input
4 5
4 4 4 4
count 1 4
add 1 4 3
count 1 4
add 2 3 40
count 1 4
Output
4
4
4

给你n个数,实现两种操作,一种操作是把一段区间的数增加某个值,另一个操作是查询一段区间内的数满足"幸运数"要求的总个数
因为题目已保证一个数的值不会超过10000,所以我们可以先把1~10000的幸运数找出来,或者直接打一个表,这样查询一个数是否是幸运数的时间复杂度就是O(1)
我是用树状数组实现的,用线段树应该更快

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#define LL long long
using namespace std;

int a[100001],c[100002],kk[10002]={0};
int maxn;

inline int lowbit(int a)
{
    return a&(-a);
}

void add(int x,int num)
{
    while(x<=maxn)
    {
        c[x]+=num;
        x+=lowbit(x);
    }
}
int getsum(int x)
{
    int sum=0;
    while(x)
    {
        sum+=c[x];
        x-=lowbit(x);
    }
    return sum;
}
bool jug(int a)
{
    while(a)
    {
        if(a%10!=4&&a%10!=7) return 0;
        a/=10;
    }
    return 1;
}
int main()
{
    int i,ans,n,m,b,a1,c1,x1,x2;
    char s[10];
    for(i=1;i<=10001;i++)
        if(jug(i)) kk[i]=1;
    while(~scanf("%d %d",&n,&m))
    {
        maxn=n;
        for(i=0; i<=n+1; i++)
            c[i]=0;
        for( i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            if(kk[a[i]]==1) add(i,1);
        }
        while(m--)
        {
            scanf("%s",s);
            if(s[0]=='c')
            {
                scanf("%d %d",&a1,&b);
                printf("%d\n",getsum(b)-getsum(a1-1));
            }
            else
            {
                scanf("%d %d %d",&a1,&b,&c1);
                for(i=a1; i<=b; i++)
                {
                    x1=kk[a[i]];
                    a[i]+=c1;
                    x2=kk[a[i]];
                    if(x1==1&&x2==0) add(i,-1);
                    else if(x1==0&&x2==1) add(i,1);
                }
            }
        }
    }
    return 0;
}



### Codeforces 887E Problem Solution and Discussion The problem **887E - The Great Game** on Codeforces involves a strategic game between two players who take turns to perform operations under specific rules. To tackle this challenge effectively, understanding both dynamic programming (DP) techniques and bitwise manipulation is crucial. #### Dynamic Programming Approach One effective method to approach this problem utilizes DP with memoization. By defining `dp[i][j]` as the optimal result when starting from state `(i,j)` where `i` represents current position and `j` indicates some status flag related to previous moves: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN = ...; // Define based on constraints int dp[MAXN][2]; // Function to calculate minimum steps using top-down DP int minSteps(int pos, bool prevMoveType) { if (pos >= N) return 0; if (dp[pos][prevMoveType] != -1) return dp[pos][prevMoveType]; int res = INT_MAX; // Try all possible next positions and update 'res' for (...) { /* Logic here */ } dp[pos][prevMoveType] = res; return res; } ``` This code snippet outlines how one might structure a solution involving recursive calls combined with caching results through an array named `dp`. #### Bitwise Operations Insight Another critical aspect lies within efficiently handling large integers via bitwise operators instead of arithmetic ones whenever applicable. This optimization can significantly reduce computation time especially given tight limits often found in competitive coding challenges like those hosted by platforms such as Codeforces[^1]. For detailed discussions about similar problems or more insights into solving strategies specifically tailored towards contest preparation, visiting forums dedicated to algorithmic contests would be beneficial. Websites associated directly with Codeforces offer rich resources including editorials written after each round which provide comprehensive explanations alongside alternative approaches taken by successful contestants during live events. --related questions-- 1. What are common pitfalls encountered while implementing dynamic programming solutions? 2. How does bit manipulation improve performance in algorithms dealing with integer values? 3. Can you recommend any online communities focused on discussing competitive programming tactics? 4. Are there particular patterns that frequently appear across different levels of difficulty within Codeforces contests?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值