【牛客练习赛64】前三题题解
A
解法:贪心,构造
题意:给定了n个1,m个2,k个4,构造一个n+m+k的序列,求1412的子序列最多个数。
思路:很显然,将1分为两堆,把所有的4都放进两堆的中间,所有的2放在最右边时,能获得最多的1412子序列个数,例如1412,1144112,144122,...
最终输出
代码如下:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
inline char nc()
{
static char buf [100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
static char c=nc();
int x=0,f=1;
for(;c>'9'||c<'0';c=nc())
if(c=='-') f=-1;
for(;c<='9'&&c>='0';c=nc())
x=(x<<3)+(x<<1)+c-48;
return x*f;
}
const int N = 2e1 + 10;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int main()
{
// std::ios::sync_with_stdio(false);
// std::cin.tie(0);
int t;
LL n, m, k, ans;
cin >> t;
while(t--){
cin >> n >> m >> k;
ans = 0;
if(n < 2|| m < 1|| k < 1) //这一步其实不必要
cout << 0 << endl;
else{
LL tmp = n / 2;
n -= tmp;
ans = n * tmp * m * k;
cout << ans << endl;
}
}
return 0;
}
B
思路:统计每一个点的度数,那么距离该点为2的个数为与它相连的点的度数减1之和或者说与它相连的点的度数之和减去相连点的个数。
代码如下:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
inline char nc()
{
static char buf [100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
static char c=nc();
int x=0,f=1;
for(;c>'9'||c<'0';c=nc())
if(c=='-') f=-1;
for(;c<='9'&&c>='0';c=nc())
x=(x<<3)+(x<<1)+c-48;
return x*f;
}
const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int tree[N];
struct node{
int x, y;
}root[N];
LL ans[N];
int main()
{
// std::ios::sync_with_stdio(false);
// std::cin.tie(0);
int t, x, y;
cin >> t;
for(int i = 1;i < t;i++){
cin >> root[i].x >> root[i].y;
tree[root[i].x]++;
tree[root[i].y]++;
}
for(int i = 1;i < t;i++){
ans[root[i].x] += tree[root[i].y] - 1;
ans[root[i].y] += tree[root[i].x] - 1;
}
for(int i = 1;i <= t;i++)
cout << ans[i] << endl;
return 0;
}
C
解法:数学
思路:看到这条式子 ,第一反应可能会觉得头大。那么来化简一下。
假设
时,可以写出
化简一下就得到,
同理,时,可以得到
就有
就有
整理一下变成
可以发现这个式子就变成了
那么这道题就完成了,可以用前缀和来处理
代码如下:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
inline char nc()
{
static char buf [100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
static char c=nc();
int x=0,f=1;
for(;c>'9'||c<'0';c=nc())
if(c=='-') f=-1;
for(;c<='9'&&c>='0';c=nc())
x=(x<<3)+(x<<1)+c-48;
return x*f;
}
const int N = 2e5 + 10;
const int MOD = 1e9 + 7;
const int inf = 0x3f3f3f3f;
LL a[N];
LL b[N];
LL s[N];
int main()
{
// std::ios::sync_with_stdio(false);
// std::cin.tie(0);
// freopen("1.in","r", stdin);
// freopen("out.out","w", stdout);
LL n, ans = 0;
cin >> n;
s[0] = 0;
for(LL i = 1;i <= n;i++){
cin >> a[i];
b[i] = ((n-i+1) * a[i]) % MOD; //求(n-i+1)*ai
s[i] = (b[i] + s[i-1]) % MOD; //前缀和处理
}
for(LL i = 1;i <= n;i++){
LL cnt = s[n] - s[i-1] + MOD;
/*血泪教训,因为在计算前缀和的时候取了模,那么前缀和数组里的数组不再成单调,就可能最后一项减去i-1项时出现负数,导致最后结果算错,加上1个MOD就能处理掉负数的情况*/
ans = (ans + (i * (a[i] * cnt % MOD) % MOD) % MOD) % MOD;
}
cout << ans << endl;
return 0;
} 