周末练习1

传送门:点击打开链接

B - B

Gym - 101532B

You are given an array a consisting of n elements a1, a2, ..., an. Array a has a special property, which is:

ai = ( ai - 1 + 1) % m, for each i (1 < i ≤ n)

You are given the array a with some lost elements from it, each lost element is replaced by -1. Your task is to find all the lost elements again, can you?


Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains two integers n and m (1 ≤ n ≤ 1000) (1 ≤ m ≤ 109), where n is the size of the array, and m is the described modulus in the problem statement.

The second line of each test case contains n integers a1, a2, ..., an ( - 1 ≤ ai < m), giving the array a. If the ith element is lost, then ai will be -1. Otherwise, ai will be a non-negative integer less than m.

It is guaranteed that the input is correct, and there is at least one non-lost element in the given array.

Output

For each test case, print a single line containing n integers a1, a2, ..., an, giving the array a after finding all the lost elements.

It is guaranteed that an answer exists for the given input.

Example
Input
4
5 10
1 2 3 4 5
4 10
7 -1 9 -1
6 7
5 -1 -1 1 2 3
6 10
5 -1 7 -1 9 0
Output
1 2 3 4 5
7 8 9 0
5 6 0 1 2 3
5 6 7 8 9 0
Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.


题意:
给你一个规律,然后给你一些已知的数,让你求一些确实的数。
思路:
标记下来确定的数的位置,然后向右遍历求值,向左遍历求值即可。
代码:
#include <bits/stdc++.h>
using  namespace std;
int n,m;
int a[100005];
int pos;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=n;i++)
        {
            if(a[i]!=-1)
            {
                pos=i;
                break;
            }
        }
        for(int i=pos+1;i<=n;i++)
        {
            a[i] = (a[i-1] + 1) % m;
        }
        for(int i=pos-1;i>=1;i--)
        {
            a[i] =(a[i+1] - 1 + m ) % m;
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d ",a[i]);
        }
        printf("\n");
    }
    return 0;
}

D - D

Gym - 101532D

Yousef has a string s that is used to build a magical string w by repeating the string s infinitely many times. For example, if s = aabbb , then w = aabbbaabbbaabbbaabbb....

Mohammad always claims that his memory is strong, and that his ability to count is very high, so Yousef decided to hold a test for Mohammad, in order to know the truth of his claims.

Yousef will give Mohammad q queries, such that each query consisting of two integers l and r, and a lowercase English letter c. The answer of each query is how many times the letter c appears between the lth and rth letters in string w.

Mohammad must answer all the queries correctly, in order to proof his claims, but currently he is busy finishing his meal. Can you help Mohammad by answering all queries?


Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains two integers n and q (1 ≤ n ≤ 104) (1 ≤ q ≤ 105), where n is the length of string s, and q is the number of queries.

The second line of each test case contains the string s of length n consisting only of lowercase English letters.

Then q lines follow, each line contains two integers l and r and a lowercase English letter c (1 ≤ l ≤ r ≤ 109), giving the queries.

Output

For each query, print a single line containing how many times the letter c appears between the lth and rth letters in string w.

Example
Input
1
8 5
abcabdca
1 8 c
1 15 b
4 9 a
5 25 d
2 7 c
Output
2
4
3
3
2
Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.


题意:给你一个可以重复无限次的字符串,求某个区间内某一字符串的个数。
思路:
这个题耽误了很长时间,就是因为一开始没有想到提前记录一下在i个位置上,他前面有多少个和它相同的字符。具体来说:
先用一个num[26][n]的二维数组,记录第i个字符在j之前出现的次数,这样只需处理区间内有多少个给定的字符串,然后在单独处理一下两边的边界即可,如何使边界处理起来比较方便?这就是这个题目关键,我们要求区间l~r,可以用区间1~r减去区间1~l-1即可。
代码:
#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
using  namespace std;
typedef long long LL;
int n,q;
char s[10005];

int num[26][10005];  //i个字母在j位置前出现次数

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&n,&q);
        scanf("%s",&s);
        for (int i=0;i<26 ; i++)
        {
            int nnn=0;
            for(int j=0;j<n;j++)
            {
                if(s[j]-'a' == i)
                {
                    nnn++;
                }
                num[i][j+1] = nnn;  //此处j+1是为了使字符从1开始,否则比较容易乱
            }
            //cout<<nnn<<"---"<<endl;
        }

        while(q--)
        {
            LL l, r ;

            char ch;
            scanf("%lld %lld %c",&l,&r,&ch);
            LL sum_l = 0;
            LL sum_r = 0;
            l--;
            sum_l = (l / n) * num[ch-'a'][n] + num[ch-'a'][l % n];  //1-l-1的某个字符的个数
            sum_r = (r / n) * num[ch-'a'][n] + num[ch-'a'][r % n]; //1-r的某个字符的个数
           /* cout<<"l/n="<<l/n<<endl; 
            cout<<"r/n="<<r/n<<endl;
            cout<<"l%n="<<(l+n)%n<<endl;
            cout<<"r%n="<<(r+n)%n<<endl;
            cout<<"sum_l="<<sum_l<<endl;
            cout<<"sum_r="<<sum_r<<endl;*/
            LL sum = sum_r - sum_l;  //相减即为结果
            printf("%lld\n",sum);
        }
    }
    return 0;
}

F - F

Gym - 101532G
Statements

Alaa sometimes feels bored at work, so at such times she starts playing with a beautiful array a consisting of n integers a1, a2, ..., an.

Alaa starts counting the number of magical indices in the array a. An index x is said to be magical if it satisfying the following rules:

  1. 1 < x < n
  2. ay ≤ ax, for each y (1 ≤ y < x).
  3. ax ≤ az, for each z (x < z ≤ n).

Can you help Alaa by counting the number of magical indices in the array a.

Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains an integer n (1 ≤ n ≤ 106), where n is the size of the array a.

The second line of each test case contains n integers a1, a2, ..., an (1 ≤ ai ≤ 106), giving the array a.

Output

For each test case, print a single line containing the number of magical indices in the array a.

Example
Input
2
8
2 1 3 4 6 5 7 9
6
4 2 7 9 8 10
Output
3
1
Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.


题意:在一个数组中,有多少个满足比左边的数均大,比右边得数均小的数。
思路:
首先,正向求一遍最大,然后再反向求一遍最小,最后在每个元素位置进行一下判断即可
代码:
#include <bits/stdc++.h>
#define INF 0x7f7f7f7f
#define ll long long
#define mod 1000000007
using namespace std;
int dpf[1000010],dpb[1000010];
int a[1000010];
int main()
{
    int t;
    scanf("%d",&t);//cin>>t;
    while(t--)
    {
        int n,i,res=0;
        scanf("%d",&n);//cin>>n;
        scanf("%d",&a[0]);//cin>>a[0];
        dpf[0]=a[0];
        for(i=1;i<n;i++)
        {
            scanf("%d",&a[i]);//cin>>a[i];
            dpf[i]=max(a[i],dpf[i-1]);  //正像最大
        }
        dpb[n-1]=a[n-1];
        for(i=n-2;i>=0;i--)
        {
            dpb[i]=min(a[i],dpb[i+1]); //反向最小
        }
        for(i=1;i<n-1;i++)
        {
            if(a[i]>=dpf[i-1]&&a[i]<=dpb[i+1])   //关键
            {
                res++;
            }
        }
        printf("%d\n",res);//cout<<res<<endl;
    }
   return 0;
}

G - G

Gym - 101532H

Husam has a lot of free time, so he is using this time in repairing corrupted binary images.

A Binary image can be represented as 2-dimensional array consisting of n rows, each of which is divided into m columns. The rows are numbered from 1 to n from top to bottom, and the columns are numbered from 1 to m from left to right. Each cell is identified by a pair (x, y), which means that the cell is located at row x and column y. The possible values in the binary images are either zero or one.

A binary image is good if all cells in the first row, last row, first column, and last column are ones. Otherwise, the binary image is corrupted. If the binary image is corrupted, Husam will fix it.

Husam wants to fix the image with the minimum number of moves, such that in each move he can swap the values at two different cells.

Can you help Husam by calculating the minimum number of required moves to fix the image?


Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains two integers n and m (3 ≤ n, m ≤ 50), where n is the number of rows in the binary image, and m is the number of columns in each row.

Then n lines follow, each line contains m characters, giving the binary image. All values in the binary image are either zero or one.

Output

For each test case, print a single line containing -1 if Husam cannot fix the binary image. Otherwise, print the minimum number of required moves to fix the image.

Example
Input
3
3 3
111
101
111
4 4
1111
0111
1000
1111
4 5
10101
01010
10101
01010
Output
0
2
-1
Note

In the first test case, the image is good. In the second test case, Husam needs to swap the values of cells (2, 1) and (2, 2), and swap the values of cells (2, 3) and (3, 4), in order to fix the image.


题意:
移动多少步使得第一行第一列最后一行最后一列均为1,注意移动可以任意两个位置(这样问题就很简单)
思路:记录一下,判断一下1的个数就可
代码:
#include <bits/stdc++.h>
using  namespace std;
int n,m;
char s[100];
int main()
{
    int T;
    cin>>T;
    while(T--)
    {

        cin>>n>>m;
        int num_z = 0;
        int num_o = 0;
        bool flag = true;
        for(int i = 1; i <= n; i++)
        {
            cin>>s;
            for(int j=0;j<m;j++)
            {
                if(i==1 || j==0 || i==n || j==m-1)
                {
                    if(s[j]=='0')
                    {
                        flag = false;
                        num_o ++;
                    }
                }
                if(s[j] == '1')
                    num_z++;
            }
        }
        if(flag==true)
        {
            printf("0\n");
            continue;
        }
        int num = 2*n + 2*m - 4;
        if(num > num_z)
        {
            printf("-1\n");
            continue;
        }
        printf("%d\n",num_o);
    }
    return 0;
}

Since the problem set was hard, here is an easy task for you to solve.

You are given an array a consisting of n integers, and your task is to calculate the summation of the multiplication of all subsets of array a. (See the note for more clarifications)

A subset of an array a is defined as a set of elements that can be obtained by deleting zero or more elements from the original array a.


Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains an integer n (1 ≤ n ≤ 105), where n is the size of array a.

The second line of each test case contains n integers a1, a2, ..., an (1 ≤ ai ≤ 106), giving the array a.

Output

For each test case, print a single line containing the summation of the multiplication of all subsets of array a. Since this number may be too large, print the answer modulo 109 + 7.

Example
Input
3
3
1 2 3
2
3 5
1
4512
Output
23
23
4512
Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

In the first test case, the array a has 6 subsets, and the answer is calculated as follow:

(1) + (2) + (3) + (1 × 2) + (1 × 3) + (2 × 3) + (1 × 2 × 3) = 23
.

题意:
求一个集合里面的子集,每个子集将元素相乘,然后在将不同的子集得到的乘积加起来。
思路:
规律题,以1、2、3为例:
以1结尾:1
以2结尾:2 、1*2
以3结尾:3、1*3、2*3、1*2*3
可以看出规律:
sum[ i ] = sum [i - 1] + (a[ i ] + a[ i ] * sum [ i -1 ]);其中带括号的那一部分以为第i个元素结尾的乘积和。
代码:
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
const int M = 100005;
typedef long long LL;
int a[M];
LL sum[M];
int main()
{
    int T;
    int n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i = 1 ; i <= n ; i++)
        {
            scanf("%d",&a[i]);
        }
        sum[1] = a[1] ;
        for(int i = 2 ; i <= n; i++)
        {
            sum[i] = (sum[i-1] + a[i] + sum[i-1] * a[i]) % mod;
        }
        printf("%lld\n",sum[n]%mod);
    }
    return 0;
}

 


猜你喜欢

转载自blog.csdn.net/sinat_37668729/article/details/80303509