目前,我们用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; }
给定一个数组 (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.
如果数据比较多,建议使用快速读入。
我们考虑奇数位为正,偶数位为负的情况(反之考虑方法一样):
对于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; }
我们给出下列递归的合法括号序列的定义:
● 空序列是合法括号序列
● 如果s是一个合法括号序列,那么(s)也是合法括号序列
● 如果a和b是合法括号序列,那么ab也是合法括号序列
● 没有其它情况是合法括号序列
比如下列括号序列是合法括号序列
(), (()), ()(), ()(())
下列括号序列则不是
(, ), )(, ((), ((()
现在,我们要构造长度为
n
的合法括号序列,前面的一些括号已经给出,问可以构造出多少合法序列。
多组测试数据(大概 2000 ),每一组数据占两行。 第一行给出一个整数 n 。 第二行给出一个字符串代表前面已经确定的几个括号。 请处理到文件末尾。 [参数约定] 1≤n≤1000000 字符串只包含’(’和’)’,长度大于 0 并且不超过 n .
对于每一个数据,在一行中输出答案对
1000000007
取余的结果。
4 () 4 ( 6 ()
1 2 2
第一组数据只有一种可能,它就是()(). 对于第二组数据他有两种可能,他们是(()) 和()(). 对于第三种数据,两种可能是()()() 和()(()).
卡特兰数的应用~
百度百科有详细讲解~
把左括号看成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; }
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