L1-7 拼接梯子
题解:通过举多个样例我们可以发现,凡是偶数并且前n项和大于m都存在答案,那么现在已知的所有满足该条件的数都存在满足题意的答案,于是便可以通过对答案的每一项除二,构造出最高项的答案(也就是右移m),最后强调int类型二进制最高位只有32位,而答案有64位(哭惨了,只拿到20分)详见代码。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
void solve() {
int n,m;
cin>>n>>m;
int t=1;
int an=0;
for(int i=1;i<=n;i++){
t*=2;
an+=t;
}
// cout<<an<<endl;
if (an < m || m &1)
cout<<"No"<<endl;
else {
cout<<"Yes"<<endl;
int ans = -1, cnt = 0;
while (m) {
if (m & 1) ans = cnt;
m >>= 1;
++cnt;
}
cout<<(1ll<<ans);
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int e=1;
// cin>>t;
while(e -- ){
solve();
}
return 0;
}
L1-8 幻想乡炼金学
题解:写吧,模拟。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define dd(x) cout << #x << " = " << x << " "
#define de(x) cout << #x << " = " << x << endl
const ll mod = 1e9 + 7;
const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
ll gcd(ll a,ll b){return b ? gcd(b,a % b) : a;}
string s,ss,sss;
int main()
{
getline(cin,s);
for(int i = 0;i < s.size();++i){
if(s[i] != ' '){
ss += s[i];
}
}
string tmp;
int cnt = 0;
for(int i = 0;i < ss.size();++i){
if(ss[i] <= 'Z' && ss[i] >= 'A' && tmp.size()){
sss += tmp;
tmp = "";
tmp += ss[i];
}
else if(ss[i] == '('){
sss += tmp;
tmp = "";
while(ss[++i] != ')')
tmp += ss[i];
i++;
cnt = 0;
while(ss[i] != '}'){
i++;
if(ss[i] <= '9' && ss[i] >= '0'){
cnt = cnt * 10 + ss[i] - '0';
}
}
string res = "";
for(int j = 0;j < tmp.size();++j){
if(tmp[j] >= 'A' && tmp[j] <= 'Z'){
res += tmp[j];j++;
while(j < tmp.size() && tmp[j] < 'A' || tmp[j] > 'Z'){
res += tmp[j];
++j;
}
j--;
}
for(int k = 0;k < cnt;++k)
sss += res;
res = "";
}
tmp = "";
}
else if(ss[i] == '{'){
cnt = 0;
while(ss[i] != '}'){
i++;
if(ss[i] <= '9' && ss[i] >= '0'){
cnt = cnt * 10 + ss[i] - '0';
}
}
for(int j = 0;j < cnt;++j)
sss += tmp;
tmp = "";
}
else{
tmp += ss[i];
}
}
sss += tmp;
cout << sss << endl;
return 0;
}
L2-1 特殊的沉重球
题解:相当于枚举第i个物品放在哪个球里,一个简单的dfs就可以解决,要注意剪枝,回溯
代码:
#include <bits/stdc++.h>
using namespace std;
int n, m;
int w[30];
int sum[30];
int ans = 20;
void dfs(int u, int k)
{
if (k >= ans)
return;
if (u == n)
ans = k;
for (int i = 0; i < k; i++)
if (sum[i] + w[u] <= m)
{
sum[i] += w[u];
dfs(u + 1, k);
sum[i] -= w[u];
}
sum[k] = w[u];
dfs(u + 1, k + 1);
sum[k] = 0;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> w[i];
sort(w, w + n, greater<int>());
dfs(0, 0);
cout << ans << endl;
return 0;
}
L2-2 又见火车入栈
题解:手写栈,模拟一下过程,对所有的查询排一个序,我卡过去的,即使开了输入输出流也过不了,最后改成scanf才过的
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
// inline int read() {
// int s = 0, w = 1; char ch = getchar();
// while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
// while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
// return s * w;
// }
int n,w;
struct mp{
int x,y,w;
bool operator < (const mp& a)const {
if (x == a.x) return y < a.y;
return x < a.x;
}
}op[1000100];
int ans[1000100];
bool vis[1000100];
int kp[1000100];
void solve(){
scanf("%d",&n);
for(int i=0;i<n;i++){
char s[5];
scanf("%s",s);
if(s[0]=='i') vis[i+1]=1;
}
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++){
// cout<<1<<endl;
int l , r ;
scanf("%d%d",&l,&r);
op[i]={l,r,i};
}
sort(op+1,op+m+1);
int k = 0, num = 0;
int top=0;
for (int i = 1; i <= m; ++i) {
while (op[i].x != k) {
if (vis[++k]) kp[++top] = ++num;
else --top;
}
ans[op[i].w] = kp[op[i].y];
}
for(int i=1;i<=m;i++){
printf("%d\n", ans[i]);
}
}
signed main(){
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int t=1;
// cin>>t;
while(t--){
solve();
}
}
L2-3 新旷野地带
题解:组合数学题。首先选取kk行kk列,然后在这kk行kk列里面进行全排列。
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
#define int long long
const int mod=1e9+7,N=1e6+5;
int n,m,k;
int in[N],f[N];
int qpow(int a,int p){
int res=1;
while(p){
if(p&1) res=res*a%mod;
a=a*a%mod;
p>>=1;
}
return res;
}
int ans(int x,int y){
if(x<y) return 0;
return f[x]*in[y]%mod*in[x-y]%mod;
}
void solve(){
cin>>n>>m>>k;
f[0]=1;
in[0]=1;
f[1]=1;
in[1]=1;
for(int i=2;i<=N;i++){
f[i]=f[i-1]*i%mod;
in[i]=qpow(f[i],mod-2);
}
int res=0;
for(int i=1;i<=min({k, n, m});i++){
res=(res+ans(n,i)*ans(m,i)%mod*f[i])%mod;
}
cout<<res<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
// cin>>t;
while(t--){
solve();
}
}
L2-4 缘之空
题解:很经典的LCA问题,只需要找到父节点,然后套板子就行了
代码:
#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
int n,q;
vector<int>a[100010];
int dev[100010];
int f[100010][20];
int ff[100010];
void dfs(int u,int fa){
dev[u]=dev[fa]+1;
f[u][0]=fa;
for(int i=1;i<=17;i++){
f[u][i]=f[f[u][i-1]][i-1];
}
for(auto v:a[u]){
if(v!=fa) dfs(v,u);
}
}
int ans=0;
int lca(int x,int y){
if(dev[x]<dev[y]) swap(x,y);
for(int i=17;i>=0;i--){
if(dev[f[x][i]]>=dev[y]) {
x = f[x][i], ans += pow(2, i);
}
}
if(x==y) return -1;
// cout<<ans<<endl;
for(int i=17;i>=0;i--){
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i],ans+=2*pow(2,i);
}
// cout<<f[x][0]<<" "<<f[y][0]<<endl;
ans+=2;
return ans+2;
}
void solve(){
cin>>n>>q;
for(int i=0;i<n-1;i++){
int x,y;
cin>>x>>y;
ff[y]=x;
a[x].push_back(y);
}
int fa=0;
for(int i=1;i<=n;i++){
if(ff[i]==0){
fa=i;
break;
}
}
dfs(fa,0);
// for(int i=1;i<=n;i++){
// cout<<dev[i]<<endl;
// }
//for(int i=0;i<n-1;i++){
// for(int j=0;j<=15;j++){
// cout<<f[i][j]<<" ";
// }
// cout<<endl;
//}
while(q--){
int x,y;
cin>>x>>y;
ans=0;
int an=lca(x,y);
if(ans>=5&&an!=-1)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
cout<<ans<<endl;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t=1;
// cin>>t;
while(t--){
solve();
}
}