PM2.5
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1346 Accepted Submission(s): 571
问题描述
目前,我们用PM2.5的含量来描述空气质量的好坏。一个城市的PM2.5含量越低,它的空气质量就越好。所以我们经常按照PM2.5的含量从小到大对城市排序。一些时候某个城市的排名可能上升,但是他的PM2.5的含量也上升了。这就意味着他的空气质量并没有改善。所以这样的排序方式是不合理的。为了使得排序合理,我们提出了一个新的排序方法。我们按照两个PM2.5含量测量的差值(第一次-第二次)来对他们按降序排序,如果有重复,按照第二次的测量值升序排序,如果还有重复,按照输入的顺序排序。
输入描述
多组测试数据(大概 100 组),每一组测试数据第一行先给出一个整数 n ,代表有 n 个城市需要被排序。城市被从 0 到 n−1 标号。接下来 n 行,每一含有两个整数代表每一个城市第一次和第二次被测量的PM2.5值。第 i 行描述城市 i−1 的信息。 请处理到文件末尾。 [参数说明] 所有整数都在 [1,100] 的范围内。
输出描述
对于每一个数据,输出排好序之后的城市ID。
输入样例
2 100 1 1 2 3 100 50 3 4 1 2
输出样例
0 1 0 2 1
直接sort排序,在cmp里面处理一下。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n;
struct data
{
int x,y,d,id;
}a[10005];
bool cmp(data a,data b)
{
if (a.d==b.d)
{
if (a.y==b.y) return a.id<b.id;
return a.y<b.y;
}
return a.d>b.d;
}
int main()
{
while (scanf("%d",&n)!=EOF)
{
for (int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y),a[i].d=a[i].x-a[i].y,a[i].id=i;
sort(a+1,a+1+n,cmp);
for (int i=1;i<n;i++)
cout<<a[i].id-1<<" ";
cout<<a[n].id-1<<endl;
}
return 0;
}
Negative and Positive (NP)
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1161 Accepted Submission(s): 59
问题描述
给定一个数组 (a0,a1,a2,⋯an−1) 和一个整数 K , 请来判断一下是否存在二元组 (i,j)(0≤i≤j<n) 使得 NP−sum(i,j) 刚好为 K 。这里 NP−sum(i,j)=ai−ai+1+ai+2+⋯+(−1)j−iaj 。
输入描述
多组测试数据。在文件的第一行给出一个 T ,表示有 T 组数据。 在接下来的 2∗T 行里,将会给出每一组数据。 每一组数据占两行,第一行包含 n 和 K 。 第二行包含 (a0,a1,a2,⋯an−1) 以一个空格分开。 [参数说明] 所有输入均为整数。 0<T≤25,1≤n≤1000000,−1000000000≤ai≤1000000000,−1000000000≤K≤1000000000
输出描述
对于每一个数据,输出占一行,输出格式是Case #id: ans,这儿id是数据编号,从1开始,ans是根据是否找到满足的二元组而定为“Yes.” 或 “No.” (不包含引号) 看样例可以获得更多的信息。
输入样例
2 1 1 1 2 1 -1 0
输出样例
Case #1: Yes. Case #2: No.
Hint
如果数据比较多,建议使用快速读入。
我们考虑奇数位为正,偶数位为负的情况(反之考虑方法一样):
对于sum[i](i%2=0)如果i+1作第一位,能使得结果为k的话,一定存在sum[i]+k这个数,如何快速判断是否存在sum[i]+k呢?
我比赛用了map,结果mle+tle。。
其实set和hash+链表都可以过,代码是hash+链表。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
#define LL long long
#define mod 1000007
using namespace std;
LL x[1000005];
struct edge
{
LL v;
int ne;
}e[1100000];
int a[1000005],h[1100000],tot=0,n,T,k;
void read(int &tmp)
{
tmp=0;
char ch=getchar();
int fu=1;
for (;ch<'0'||ch>'9';ch=getchar())
if (ch=='-') fu=-1;
for (;ch>='0'&&ch<='9';ch=getchar())
tmp=tmp*10+ch-'0';
tmp*=fu;
}
void Insert(LL x)
{
int ha=x%mod;
if (ha<0) ha=-ha;
for (int i=h[ha];i;i=e[i].ne)
if (e[i].v==x) return;
e[++tot].ne=h[ha];
h[ha]=tot;
e[tot].v=x;
}
bool Find(LL x)
{
int ha=x%mod;
if (ha<0) ha=-ha;
for (int i=h[ha];i;i=e[i].ne)
if (e[i].v==x) return 1;
return 0;
}
void Clear()
{
for (int i=1;i<=n;i++)
{
int ha=x[i]%mod;
if (ha<0) ha=-ha;
h[ha]=0;
}
tot=0;
}
int main()
{
read(T);
for (int i=1;i<=T;i++)
{
read(n),read(k);
x[0]=0;
int f=0;
for (int i=1;i<=n;i++)
{
read(a[i]);
if (i&1)
x[i]=x[i-1]+a[i];
else x[i]=x[i-1]-a[i];
}
for (int i=n;i;i--)
{
if (x[i]==k)
{
f=1;break;
}
if ((i&1)==0)
{
if (Find(x[i]+k)) {f=1;break;}
}
else if (Find(x[i]-k)) {f=1;break;}
Insert(x[i]);
}
printf("Case #%d: ",i);
if (f) printf("Yes.\n");
else printf("No.\n");
Clear();
}
return 0;
}
Brackets
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 215 Accepted Submission(s): 33
问题描述
我们给出下列递归的合法括号序列的定义:
● 空序列是合法括号序列
● 如果s是一个合法括号序列,那么(s)也是合法括号序列
● 如果a和b是合法括号序列,那么ab也是合法括号序列
● 没有其它情况是合法括号序列
比如下列括号序列是合法括号序列
(), (()), ()(), ()(())
下列括号序列则不是
(, ), )(, ((), ((()
现在,我们要构造长度为
n
的合法括号序列,前面的一些括号已经给出,问可以构造出多少合法序列。
输入描述
多组测试数据(大概 2000 ),每一组数据占两行。 第一行给出一个整数 n 。 第二行给出一个字符串代表前面已经确定的几个括号。 请处理到文件末尾。 [参数约定] 1≤n≤1000000 字符串只包含’(’和’)’,长度大于 0 并且不超过 n .
输出描述
对于每一个数据,在一行中输出答案对
1000000007
取余的结果。
输入样例
4 () 4 ( 6 ()
输出样例
1 2 2
Hint
第一组数据只有一种可能,它就是()(). 对于第二组数据他有两种可能,他们是(()) 和()(). 对于第三种数据,两种可能是()()() 和()(()).
卡特兰数的应用~
百度百科有详细讲解~
把左括号看成1,右括号看成-1,然后问题就变成了求1,-1有多少种排列方法,使得前缀和始终>=0。
百度百科扩展部分有详解~我大概说一下思路
先考虑使得前缀和>0的情况,转化为几何问题;然后再考虑>=0的情况。
最后得出的答案是C(n+m-1,m)-C(n+m-1,m-1)
这道题可以先求出需要填a1个左括号,b1个右括号,相当于从(a1,b1)走到(n/2,n/2)不跨过对角线的方案数。
相当于求(0,0)到(n/2-a1,n/2-b1)不跨过对角线的方案数,直接代到上面的式子即可。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <string>
#define mod 1000000007
#define M 1000000+5
#define LL long long
using namespace std;
int n;
char s[M];
LL fac[M],inv[M];
LL Pow(LL a,int n)
{
LL ans=1LL,base=a;
while (n)
{
if (n&1) ans=ans*base%mod;
base=base*base%mod;
n>>=1;
}
return ans;
}
void Prepare()
{
fac[0]=1LL;
for (int i=1;i<=M-3;i++)
{
int x=i;
fac[i]=fac[i-1]*(LL)x%mod;
}
inv[M-3]=Pow(fac[M-3],mod-2);
for (int i=M-4;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%mod;
}
LL Getc(int n,int m)
{
if (n<m) return 0LL;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
Prepare();
while (scanf("%d",&n)!=EOF)
{
scanf("%s",s);
int cnt=0,f=1,a=n/2,b=n/2,l=strlen(s);
for (int i=0;i<l;i++)
{
if (s[i]=='(') cnt++,a--;
else cnt--,b--;
if (cnt<0)
{
f=0;
break;
}
}
if (!f||n%2==1||a<0||b<0)
{
puts("0");
continue;
}
printf("%lld\n",(Getc(a+b,a)-Getc(a+b,a-1)+mod)%mod);
}
return 0;
}
(卡特兰数太神奇了~)
Equation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 49 Accepted Submission(s): 18
问题描述
Gorwin 对等式非常感兴趣。前几天他获得了这么一个等式 x1+x2+x3+⋯+xn=n , 这里0≤xi≤nfor1≤i≤nxi≤xi+1≤xi+1for1≤i≤n−1对于一个给定的 n ,Gorwin想要知道有多少 xi 的组合满足上述等式。 由于结果比较大,输出答案对 m 取余的结果就行。
输入描述
多组测试数据。文件的第一行给出一个 T ,表示下面有 T 组数据。下面 T 行每行给出两个整数 n,m 以一个空格分开。 [参数约定] 1≤T<20,1≤n≤50000,1≤m≤1000000000
输出描述
对于每一个数据输出占一行,输出格式为Case #id: ans,这儿id是数据编号从1开始,ans是你输出的答案。 看样例得到更多信息。
输入样例
2 3 100 5 100
输出样例
Case #1: 2 Case #2: 3