A
Decription:
若数列A存在位置k,满足
①i<k,ai<ai+1
②i>=k,ai>ai+1
则称该数列为单峰数列
给出正整数n,求全排列n中存在多少个单峰数列
Input
给出1个正整数n
Output
单峰数列个数(对10^9+7取模)
Sample Input:
3
Sample Output:
4
Data Constraint
20%:n ≤ \leq ≤ 10
50%:n ≤ \leq ≤ 10^5
100%:2 ≤ \leq ≤ n ≤ \leq ≤ 10^18
思路:
数据这么大,明显是数论,是的,尝试着就来推一波,对于最大值n来说,他肯定就是那个峰值,那么我们试着看一下,峰值肯定是n,考虑n左右放哪些数,决定放哪些数以后,排列是固定的即n左边放的数单调递增,n右边放的数单调递减方案数为C(n-1,0)+C(n-1,1)+…+C(n-1,n-1)=
2
(
n
−
1
)
2^{(n-1)}
2(n−1)
那么不就是一道水体了吗,快速幂取模走起。
#include<iostream>
#include<cstdio>
#define ll long long
#define mod 1000000007
using namespace std;
ll n;
ll ksm(ll x,ll y)
{
ll res=1;
while(y)
{
if(y&1) res=(res%mod*x%mod)%mod;
x=(ll)(x*x)%mod,y>>=1;
}
return res;
}
int main()
{
scanf("%lld",&n);
n--;
printf("%lld",ksm(2,n));
return 0;
}
B
Decription:
XJQ要做N件事,需要消耗它不同的精力,做完之后还会获得一定的信誉。对于每件事他可以选择做或不做,而且他还有可能真香一些事,真香之后这些事就不能再做了。对于每次真香,他都想知道以他的精力,最多可以获得多少信誉。
Input
第一行2个正整数n,m表示有n件事它开始拥有的精力
第n行,每行两个数,表示需要精力和可以获得的信誉
接下来n-1行一个数表示了他真香了哪件事
每次真香对下一次真香有影响
Output
第一行为开始时可以获得的最多信誉
接下来n-1行表示他真香了某件事后可以获得的最多信誉
Sample Input:
5 20
7 1
1 1
13 1
1 9
1 16
1
4
2
3
Sample Output:
27
27
18
17
16
Data Constraint
1~3:n,m ≤ \leq ≤ 100
3~5:n ≤ \leq ≤ 1000,m ≤ \leq ≤ 5000
6~10:n ≤ \leq ≤ 4000,m ≤ \leq ≤ 10000
其他数均为正整数,且不大于10000
思路:
看得出来是个01背包,倒过来dp不就完事了?秒了吧?
#include<iostream>
#include<cstdio>
#define M 10000
#define N 4000
using namespace std;
int n,m,dp[M+11],f[N+11],val[N+11],ban[N+11],maxn,ans[N+11];
bool bo[N+11];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d%d",&f[i],&val[i]);
for(int i=1;i<=n-1;i++) scanf("%d",&ban[i]),bo[ban[i]]=1;
for(int i=1;i<=n;i++)
{
if(!bo[i])
{
ban[n]=i;
break;
}
}
for(int i=n;i>=1;i--)
{
maxn=0;
for(int j=m;j>=f[ban[i]];j--)
dp[j]=max(dp[j-f[ban[i]]]+val[ban[i]],dp[j]),maxn=max(dp[j],maxn);
ans[i]=maxn;
}
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}
C
Decription:
给定一个长度为n的数列a,有m次操作,操作分两种:
1 给出[l,r],表示将此区间的数轮转一次,即变成 a r a_r ar, a l a_l al… a r − 1 a_{r-1} ar−1
2 给出[l,r]和k,询问此区间内 a i a_i ai==k的个数
Input
第一行给出n,m
第二行给出序列a
接下来m行给出m次操作
Output
对于每个询问,给出一行表示答案
Sample Input:
7 6
1 2 2 3 2 1 3
2 3 6 2
1 1 6
2 2 4 1
1 3 6
2 6 7 3
2 3 5 2
Sample Output:
2
1
2
3
Data Constraint
1~3:n,m ≤ \leq ≤ 100
3~5:n ≤ \leq ≤ 1000,m ≤ \leq ≤ 5000
6~10:n ≤ \leq ≤ 4000,m ≤ \leq ≤ 10000
其他数均为正整数,且不大于10000
思路:
分块,我的分块写炸了,总的复杂度为O(n
n
\sqrt{n}
n)
转载了disPlayLzy_的博客代码,大家先看一看,小编会后续更改的,再次感谢disPlayLzy_。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define N 100005
using namespace std;
int A[335][N], Belong[N], C[355], D[355], num, cnt, n, m;
void read(int &x)
{
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
x = x * f;
}
deque <int> Q[N];
int main()
{
// freopen("queue.in", "r", stdin);
// freopen("queue.out", "w", stdout);
read(n); read(m);
num = sqrt(n);
for (int i = 1; i <= n; i++)
{
int x; read(x);
if (i > num * cnt) ++cnt;
Q[cnt].push_back(x);
Belong[i] = cnt, ++A[cnt][x];
}
while (m--)
{
int opt; read(opt);
if (opt == 1)
{
int l, r; read(l); read(r);
if (Belong[l] == Belong[r])
{
int G = Belong[l];
l = l % num; if (l == 0) l = num;
r = r % num; if (r == 0) r = num;
for (int i = 1; i < l; i++) //把 1~L 取出来
C[i] = Q[G].front(), Q[G].pop_front();
for (int i = 1; i <= num - r; i++)
D[i] = Q[G].back(), Q[G].pop_back();
int x = Q[G].back(); Q[G].pop_back(); Q[G].push_front(x);
for (int i = l - 1; i >= 1; i--) Q[G].push_front(C[i]);
for (int i = 1; i <= num - r; i++) Q[G].push_back(D[(num - r) - i + 1]);
}
else
{
int G = Belong[l], k = l; while (Belong[k + 1] == G) ++k;
int len1 = k - l + 1;
for (int i = 1; i <= len1; i++)
C[len1 - i + 1] = Q[G].back(), Q[G].pop_back(), A[G][C[len1 - i + 1]]--;
int F = Belong[r], h = r; while (Belong[h - 1] == F) --h;
int len2 = r - h + 1;
for (int i = 1; i <= len2; i++)
D[i] = Q[F].front(), Q[F].pop_front(), A[F][D[i]]--;
Q[G].push_back(D[len2]), A[G][D[len2]]++;
for (int i = 1; i < len1; i++) Q[G].push_back(C[i]), A[G][C[i]]++;
for (int i = len2 - 1; i >= 1; i--) Q[F].push_front(D[i]), A[F][D[i]]++;
int x = Q[F - 1].back(); if (F == G + 1) x = C[len1];
Q[F].push_front(x), A[F][x]++;
int last = C[len1];
for (int i = G + 1; i <= F - 1; i++)
{
Q[i].push_front(last); A[i][last]++;
last = Q[i].back(); Q[i].pop_back();
A[i][last]--;
}
}
}
else
{
int l, r, K, orz = 0; read(l); read(r); read(K);
if (Belong[l] == Belong[r])
{
int G = Belong[l];
l = l % num; if (l == 0) l = num;
r = r % num; if (r == 0) r = num;
for (int i = 1; i < l; i++)
C[i] = Q[G].front(), Q[G].pop_front();
for (int i = 1; i <= num - r; i++)
D[i] = Q[G].back(), Q[G].pop_back();
for (int i = l - 1; i >= 1; i--)
{
if (C[i] == K) ++orz;
Q[G].push_front(C[i]);
}
for (int i = 1; i <= num - r; i++)
{
if (D[(num - r) - i + 1] == K) ++orz;
Q[G].push_back(D[(num - r) - i + 1]);
}
orz = A[G][K] - orz;
}
else
{
int G = Belong[l], k = l; while (Belong[k + 1] == G) ++k;
int len1 = k - l + 1;
for (int i = 1; i <= len1; i++) C[len1 - i + 1] = Q[G].back(), Q[G].pop_back();
for (int i = 1; i <= len1; i++)
{
if (C[i] == K) ++orz;
Q[G].push_back(C[i]);
}
int F = Belong[r], h = r; while (Belong[h - 1] == F) --h;
int len2 = r - h + 1;
for (int i = 1; i <= len2; i++) D[i] = Q[F].front(), Q[F].pop_front();
for (int i = len2; i >= 1; i--)
{
if (D[i] == K) ++orz;
Q[F].push_front(D[i]);
}
for (int i = G + 1; i <= F - 1; i++) orz += A[i][K];
}
printf("%d\n", orz);
}
}
return 0;
}