2018.5.12—记录菜菜的一场比赛

这篇博客记录了一次编程比赛后的反思,作者发现自身基础不扎实,比赛中遇到的问题包括细节处理和题意理解。博客中详细介绍了几个比赛题目,涉及数组、模运算、最大和求解、字符串处理和回文串等概念,通过代码示例解析了解题思路。
摘要由CSDN通过智能技术生成

写个博客记录一下菜鸟成长记~

赛后认真总结反思了一下,还是基础不牢固,思路有了要么是细节处理有问题,要么是题意有遗漏。

A:说是规律。。反正我没想到。。还在研究。

B:

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

水题:就是根据一个已知的就能推其它的。

代码:

#include<bits/stdc++.h>
using namespace std;
int a[1010];
int main()
{
    int t;
    int n,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        int lala;
        for(int i=1;i<=n;i++)
        {
            if(a[i]!=-1)
            {
                a[i+1]=(a[i]+1)%m;
                lala=i;
            for(int j=i+2;j<=n;j++)
            {
                a[j]=(a[j-1]+1)%m;
            }
            break;
            }
        }
        for(int i=lala-1;i>=1;i--)
        {
            a[i]=a[i+1]-1;
            if(a[i]<0)
                a[i]+=m;
        }
        for(int i=1;i<=n;i++)
        {
            cout<<a[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

C:二分!!!

You are given an array a consisting of n element a1, a2, ..., an. For each element ai you must find another element aj (i ≠ j), such that the summation of ai and aj mod (109 + 7) (i.e. (ai + aj) % (109 + 7)) is as maximal as possible.


Can you help judges by solving this hard problem?


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


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


The second line of each test case contains n integers a1, a2, ..., an (0 ≤ ai < 109 + 7), giving the array a.


Output
For each test case, print a single line containing n space separated elements, such that the ith element is the answer to the ith element in the array a (i.e. the maximum value of (ai + aj) % (109 + 7)).


Example
Input
2
3
1 2 3
2
1000000000 1000000000
Output
4 5 5

999999993 999999993

代码:

就是找最接近(mod-a【i】-1)的那个数。可惜我二分没搜好

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[100005];
struct node
{
    int num,id;
    bool operator<(const node &aa)const
    {
        if(num!=aa.num)
        return num<aa.num;
        return id<aa.id;
    }
}b[100005];
int mod;
int main()
{
    int i,j,t,n,ant;
    scanf("%d",&t);
    mod=1000000007;
    while(t--)
    {
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            b[i].num=a[i];
            b[i].id=i;
        }
        sort(b,b+n);
        for(i=0;i<n;i++)
        {
            if(i!=0)printf(" ");
            int ans;
            ans=(mod-1-a[i]+mod)%mod;
            int l,r,mid;
            l=0;
            r=n-1;
            ant=n-1;
            while(l<=r)
            {
                mid=(l+r)>>1;
                if(b[mid].num>ans)
                {
                    r=mid-1;
                }
                else
                {
                    l=mid+1;
                    ant=mid;
                }
            }
            //printf("%d %d \n",ant,ans);
            if(b[ant].id==i)
            {
                if(ant==0)
                    ant=n-1;
                else
                ant--;
            }
            printf("%d",(a[i]+b[ant].num)%mod);
        }
        printf("\n");
    }
}

D:这道题就是用dp[i][j]表示到第i位,j字母出现的次数。预处理一下就好了。

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

代码:

#include<bits/stdc++.h>
using namespace std;
int t;
char a[10005];
int dp[10005][30];
int n,q;
int l,r;
char b;
int sum;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		memset(dp,0,sizeof(dp));
		scanf("%d%d",&n,&q); 
		cin>>a;
		dp[1][a[0]-'a']++;
		for(int i=2;i<=n;i++)
		{
			for(int j=0;j<26;j++)
			{
				dp[i][j]=dp[i-1][j];
			}
			dp[i][a[i-1]-'a']++;
		}
		while(q--)
		{
			sum=0;
			scanf("%d %d %c",&l,&r,&b);
			int ans1,ans2;
			ans1=dp[n][b-'a']*((l-1)/n)+dp[(l-1)%n][b-'a'];
			ans2=dp[n][b-'a']*(r/n)+dp[r%n][b-'a'];
			sum=ans2-ans1;
			printf("%d\n",sum);
		}
	}
	
	
	return 0;
 } 

E:暂时未看。听说是折半查找。。不会

F:好水的一道题。奈何我把大于等于当成了大于。。直到结束都没发现读错题了。。

G:水题。虽然是猜的题意

H:用bfs和dp都可以。我更喜欢dp的解法。觉得还蛮好的。

自己当时居然用dfs敲了一发,tle。真是太菜了。

Universal Studios Theme Parks announced a new game named The Crazy Jumper, that is targeted problem solving fans.


In this game, there are n large boxes numbered from 1 to n from left to right, such that the ith box (1 < i ≤ n) is located to the right of the (i - 1)th box. Each box has a color, such that ci is the color of the ith box.


The goal of the game is to reach the nth box starting from the 1st box, by jumping between the boxes. The player can do one of the following jumps:


Jump one box to the right.
If the player stands at a box of color x, he/she can jump to the closest box of color x that is to the right of him, if such box exist.
Ziad will be the first one to play the game, but he is not sure whether the game is amusing or not, so he wants to finish it with the minimum number of jumps. Can you help Ziad by telling him what is the minimum number of required jumps to reach the nth box stating from the 1st box?


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 ≤ 2 × 105), where n is the number of the boxes in the game.


The second line of each test case contains n integers c1, c2, ..., cn (1 ≤ ci ≤ 2 × 105), where ci is the color of the ith box.


Output
For each test case, print a single line containing the minimum number of required jumps to reach the nth box starting from the 1st box.


Example
Input
3
6
9 2 4 7 1 5
5
1 2 1 1 4
6
1 2 3 1 3 2
Output
5
3

2

代码:

#include<bits/stdc++.h>
using namespace std;
int a[200010];
int dp[200010];
int pos[200020];
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]);
        }
        memset(dp,0,sizeof(dp));
        memset(pos,-1,sizeof(pos));
        dp[1]=0;
        pos[a[1]]=1;
        for(int i=2;i<=n;i++)
        {
            dp[i]=dp[i-1]+1;
            if(pos[a[i]]!=-1)
            {
                dp[i]=min(dp[i],dp[pos[a[i]]]+1);
            }
            pos[a[i]]=i;
        }
        cout<<dp[n]<<endl;
    }
}

I:一道不是dp的dp题。这个状态转移方程是瞎猜的。。很不容易找了好久。。还是太菜了

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

代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int main()
{
    int t,n;
    int a[100010];
    long long dp[100010];
   // memset(dp,0,sizeof(dp));
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        dp[0]=0;
        for(int i=1;i<=n;i++)
        {
            dp[i]=(dp[i-1]*a[i]+dp[i-1]+a[i])%mod;
        }
       cout<<dp[n]<<endl;
    }
    return 0;
}

j:我喜欢这道题。

虽然只想出了一半,但是另一半真的是。。差一点。还是思维缺乏练习吧。

题意就是有几个回文串的组合。

然后有n个不同字母的组合。最多有一组是奇数才行(大于等于两组是奇数就不可能组成回文串)

然后就分成了两半。

n个位置有n种排列

然后除以相同的排列组(高中知识)。具体看代码

An anagram is a word or phrase formed by rearranging the letters of another word or phrase, using all the original letters exactly once, such as "post", "stop", and "spot".


You are given a string s consisting of lowercase English letters. Your task is to count how many distinct anagrams of the string s are palindromes.


A palindrome is a word, phrase, number, or other sequence of characters which reads the same backward as forward, such as "madam" or "racecar".


For example, "aabb" has 6 distinct anagrams, which are: "aabb", "abab", "abba", "baab", "baba", "bbaa". Two of the previous anagrams are palindromes, which are: "abba", "baab".


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 ≤ 20), where n is the length of the string s.


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


Output
For each test case, print a single line containing how many distinct anagrams of the string s are palindromes.


Example
Input
5
4
aabb
6
ababbc
6
abaaba
12
babacbcbcaca
14
aaaabbcaaaabbc
Output
2
0
3
90

105

代码:

#include<bits/stdc++.h>
using namespace std;
map<char,int>lala;
int jie(int h)
{
    int sum=1;
    for(int i=h;i>=1;i--)
    {
        sum*=i;
    }
    return sum;
}
int main()
{
    int t;
    int n;
    string h;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        cin>>h;
        for(char i='a';i<='z';i++)
        {
            lala[i]=0;
        }
        for(int i=0;i<n;i++)
        {
            lala[h[i]]++;
        }
        int num=0;
        for(char i='a';i<='z';i++)
        {
            if(lala[i]%2==1)
            {
                //cout<<i<<"    %%%"<<endl;
                num++;
            }
        }
        //cout<<num<<"  ***"<<endl;
        if(num>1)
            cout<<"0"<<endl;
        else
        {
            int kaka=1;
            for(char i='a';i<='z';i++)
            {
                lala[i]=lala[i]/2;
                kaka=kaka*jie(lala[i]);
            }
            int pp=n/2;
            int ans=jie(pp);
            cout<<ans/kaka<<endl;
        }
    }
    return 0;
}

ps:啊。有点小伤心a

这场比赛挺考验思维的。自己还要强加练习。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值