NCD 2019部分题解
A
B
C
C - Hasan and his lazy students
题目大意:求最长上升子序列的长度和个数
思路:LIS的模板 设f[i][j]数组用来表示以i结尾,长度为j的上升子序列数量
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
const int mod = 1e9 + 7;
int t, n;
int a[N], dp[N]; // dp[i]表示以i结尾的最长上升子序列的长度
ll f[N][N]; // f[i][j]表示以i结尾,长度为j的上升子序列的总个数
int main()
{
cin >> t;
while (t--)
{
cin >> n;
int mx = 1;
memset(f,0,sizeof(f));
for (int i = 0; i < n; i++)
{
cin >> a[i];
dp[i] = 1;
f[i][1] = 1;
for (int j = 0; j < i; j++)
{
if (a[j] < a[i])
{
dp[i] = max(dp[i], dp[j] + 1);
f[i][dp[j] + 1] = (f[i][dp[j] + 1] + f[j][dp[j]]) % mod;
mx = max(mx, dp[i]);
}
}
}
ll ans = 0;
for (int i = 0; i < n; i++)
ans = (ans + f[i][mx]) % mod;
cout << mx << ' ' << ans << endl;
}
system("pause");
}
D
D. Football Cup
(水题)
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int x,y,t;
int main()
{
cin>>t;
while(t--)
{
cin>>x>>y;
if(x>y) cout<<"Bashar\n";
else if(x<y) cout<<"Hamada\n";
else if(x==y) cout<<"Iskandar\n";
}
}
E
E - Adnan and the Burned drivers
F
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll t,n,k;
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
ll ans=(n-k)/6;
if(6*ans<(n-k)) ans++;
cout<<ans<<endl;
}
}
G
H
H - Mr. Hamra and his quantum particles
(并查集模板题)
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int fa[N],ran[N];
int t,n,m,q;
void init()
{
for(int i=0;i<N;i++)
fa[i]=i,ran[i]=1;
}
int find(int x)
{
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
void unit(int x,int y)
{
x=find(x),y=find(y);
if(x==y) return ;
if(ran[x]<=ran[y]) fa[x]=y;
else fa[y]=x;
if(ran[x]==ran[y]) ran[x]++;
}
bool same(int x,int y)
{
return find(x)==find(y);
}
int main()
{
cin>>t;
while (t--)
{
cin>>n>>m>>q;
init();
string s="";
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
unit(x,y);
}
for(int i=1;i<=q;i++)
{
int x,y;
cin>>x>>y;
if(same(x,y)) s+="1";
else s+="0";
}
cout<<s<<endl;
}
}
J
J- Bashar and daylight saving time
K
K- Masaoud LOVES PIZZAS
题意:求有多少个子段和不超过X
思路:预处理前缀和,对于满足的子段,每一个L端对应一个最大的R满足条件,那么小于R内的子段都满足条件,可以二分找一下R即可,最后结果为所有满足条件的子段数量和
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
ll a[N], sum[N];
ll t, n, x;
int main()
{
cin >> t;
while (t--)
{
cin >> n >> x;
memset(sum, 0, sizeof(sum));
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
}
ll ans = 0;
for (int i = 1; i <= n; i++)
{
int l = i, r = n, R = 0;
while (l <= r)
{
int mid = (l + r) / 2;
if (sum[mid] - sum[i - 1] < x) l = mid + 1, R = mid;
else r = mid - 1;
}
ans += max(0, R - i + 1);
}
cout << ans << endl;
}
}
L
L - Chemistry Exam
题目大意:求一个数二进制中1的个数
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int a[N],b[N];
int t,n;
int jg(int x)
{
int cnt=0;
while (x)
{
int m = x%2;
if(m) cnt++;
x/=2;
}
return cnt;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=jg(a[i]);
}
for(int i=1;i<=n;i++)
cout<<b[i]<<' ';
cout<<"\n";
}
}
M
M - NCD Salary
题目大意:
思路:用log转换比较 特判一下B1,B2为0的情况。
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int t;
int b1,b2,p1,p2;
int main()
{
cin>>t;
while (t--)
{
cin>>b1>>p1>>b2>>p2;
if(b1==0||b2==0)
{
if(b1==b2) cout<<"Lazy\n";
else if(b1<b2) cout<<"Congrats\n";
else cout<<"HaHa\n";
}
else{
double x1 = p1*log(b1*1.0);
double x2 = p2*log(b2*1.0);
if(fabs(x1-x2)<=1e-6) cout<<"Lazy\n";
else if(x1<x2) cout<<"Congrats\n";
else cout<<"HaHa\n";
}
}
}