2018-2019賽季多校聯合新生訓練賽第八場(2018/12/21)補題題解
阿新 • • 發佈:2018-12-22
感慨
這次題目又有了難度明顯的提升
感謝
感謝lyj大佬 lk大佬 duny大佬!!!
A 春遊(貪心)
首先可以計算一下發現實際上做33的車價效比是比較高的那麼我們應該能做33就做33
你可能會問我們取一個33與49的公倍數,說不定做49的更好?
但是實際上即使這樣還是33的花錢少!!!
這樣我們有三種可能
①人數正好是33的倍數
全部做33的車
②人數餘33小於等於16
那麼少一輛33的多一輛49的
③人數餘33大於16
多一輛33的
最終注意如果人數小於33特判一下即可
最終我們用了O(1)的時間解決了這個問題
程式碼
#include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { ios::sync_with_stdio(0); cout.tie(0); cin.tie(0); ll n; cin>>n; ll t=n%33; if(n<33) cout<<1900; else if(t>0&&t<=16) cout<<(n/33-1)*1900+3300; else if(t>16) cout<<(n/33+1)*1900; else if(t==0) cout<<(n/33)*1900; }
B 鬥地主IV(模擬)
這個不用說了吧,都會做,模擬一下就可以了
程式碼
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll num[1000]; int main() { ios::sync_with_stdio(0); cout.tie(0); cin.tie(0); ll n; cin>>n; while(n--) { ll ps,sc,cas; cin>>ps>>sc>>cas; if(cas==1) { for(int i=1;i<=4;i++) if(ps==i) num[i]+=sc*3; else num[i]-=sc; } else if(cas==2) { for(int i=1;i<=4;i++) if(ps==i) num[i]-=sc*3; else num[i]+=sc; } } for(int i=1;i<=4;i++) cout<<num[i]<<" "; }
C BMI(語法基礎)
注意用double去比較即可,如果不是good那麼for暴力求解
程式碼
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll num[10000]; int main() { ios::sync_with_stdio(0); cout.tie(0); cin.tie(0); double h,w; cin>>h>>w; h/=100; double t=w/pow(h,2); if(t>=18&&t<=24) cout<<"Good!"; else { if(t>24) { cout<<"Too fat!\n"; for(double i=w-1;i;i--) { double t1=(i)/pow(h,2); if(t1<=24) { cout<<w-i; break; } } } else if(t<18) { cout<<"Too thin!\n"; for(double i=w+1;;i++) { double t1=(i)/pow(h,2); if(t1>=18) { cout<<i-w; break; } } } } }
D 人工智慧(模擬)
這個題四個方向的車好說,皇后不好說。。。
皇后的斜向走還需要寫4個函式
我比賽的時候昏迷了用了有標記就返回,實際上完全不需要這個條件
程式碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int bk[2333][2333],mp[2333][2333];
int n;
void dfs1(int x,int y)
{
for(int i=x-1;i>=0;i--)
if(mp[i][y]==0)
bk[i][y]=1;
else if(mp[i][y]==1||mp[i][y]==2)
break;
for(int i=x+1;i<n;i++)
if(mp[i][y]==0)
bk[i][y]=1;
else if(mp[i][y]==1||mp[i][y]==2)
break;
for(int i=y-1;i>=0;i--)
if(mp[x][i]==0)
bk[x][i]=1;
else if(mp[x][i]==1||mp[x][i]==2)
break;
for(int i=y+1;i<n;i++)
if(mp[x][i]==0)
bk[x][i]=1;
else if(mp[x][i]==1||mp[x][i]==2)
break;
}
void dfs2(int x,int y)
{
if(x>=0&&y<n&&mp[x][y]==0)
bk[x][y]=1,dfs2(x-1,y+1);
else
return;
}
void dfs3(int x,int y)
{
if(x>=0&&y>=0&&mp[x][y]==0)
bk[x][y]=1,dfs3(x-1,y-1);
else
return;
}
void dfs4(int x,int y)
{
if(x<n&&y<n&&mp[x][y]==0)
bk[x][y]=1,dfs4(x+1,y+1);
else
return;
}
void dfs5(int x,int y)
{
if(x<n&&y>=0&&mp[x][y]==0)
bk[x][y]=1,dfs5(x+1,y-1);
else
return;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>mp[i][j];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(mp[i][j]==1)
bk[i][j]=1,dfs1(i,j);
else if(mp[i][j]==2)
bk[i][j]=1,dfs1(i,j),dfs2(i-1,j+1),dfs3(i-1,j-1),dfs4(i+1,j+1),dfs5(i+1,j-1);
int sum=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(!bk[i][j])
sum++;
cout<<sum;
}
E 基因鎖(KMP)
比賽的時候有小bug,沒有發現,後來詢問duny大佬才發現了bug。。。。
思路就是kmp找染色的個數。然後遍歷染色的部位一段一段的計算切點的個數
切點個數計算公式為
當前連續的染色個數/肥胖基因的長度
最後把切點加起來就可以了
程式碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int nex[6666666],mk[6666666];
char a[6666666],b[6666666];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll n,m,sum=0,re=0,ans=0;
cin>>n>>m;
cin>>a+1>>b+1;
ll len1=strlen(a+1);
ll len2=strlen(b+1);
ll j=0,p=0;
for(int i=2;i<=len1;i++)
{
while(j&&b[i]!=b[j+1])
j=nex[j];
if(b[i]==b[j+1])
j++;
nex[i]=j;
}
j=0;
for(int i=1;i<=len1;i++)
{
while(j&&a[i]!=b[j+1])
j=nex[j];
if(a[i]==b[j+1])
j++;
if(j==len2)
{
for(int k=i-j+1;k<=i;k++)
mk[k]=1;
}
}
for(int i=0;i<=len1+1;i++)
if(mk[i]==1)
re++,ans++;
else if(mk[i]==0)
sum+=re/m,re=0;
cout<<ans<<" "<<sum;
}
F 量子計算(數學)
這個題好像是高中數學競賽的真題來著
公式
程式碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll n,m;
cin>>n>>m;
if(n%2==0)
{
ll t1=m-1;
t1%=10000007;
ll re=1;
for(int i=0;i<n;i++)
re*=(m-1)%10000007,re%=10000007;
ll ans=re+t1;
ans%=10000007;
cout<<ans;
}
else
{
ll t1=m-1;
t1%=10000007;
ll re=1;
for(int i=0;i<n;i++)
re*=(m-1)%10000007,re%=10000007;
ll ans=re-t1;
ans%=10000007;
cout<<ans;
}
}
G 常州拔河(貪心)
就是我課件裡的上船問題
程式碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
int sum,id;
}num[6666666];
bool cmp(node a,node b)
{
return a.sum==b.sum?a.id<b.id:a.sum<b.sum;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>num[i].sum,num[i].id=i+1;
sort(num,num+n,cmp);
int t=n/2;
cout<<n/2<<" ";
for(int i=0;i<n;i++)
{
cout<<num[i].id<<" ";
t--;
if(t==0)
break;
cout<<num[n-1-i].id<<" ";
t--;
if(t==0)
break;
}
}
H 常州買衣服(貪心)
既然優惠後一定價格小於等於原價,那麼先對優惠後的價格進行一次排序,先買有優惠的。
再按照優惠前的排序,優惠券用光了買沒有優惠的,注意不要買重了
程式碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
int pre,now,id;
}num1[666666],num2[666666];
int bk[666666];
ll ans;
bool cmp1(node a,node b)
{
return a.now<b.now;
}
bool cmp2(node a,node b)
{
return a.pre<b.pre;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll n,k,m;
cin>>n>>k>>m;
for(int i=0;i<n;i++)
{
cin>>num1[i].pre>>num1[i].now;
num1[i].id=num2[i].id=i;
num2[i].pre=num1[i].pre;
num2[i].now=num1[i].now;
}
sort(num1,num1+n,cmp1);
sort(num2,num2+n,cmp2);
for(int i=0;i<k;i++)
{
m-=num1[i].now;
if(m>0)
ans++,bk[num1[i].id]=1;
else
break;
}
for(int i=0;i<n;i++)
{
if(!bk[num2[i].id])
{
m-=num2[i].pre;
if(m>0)
ans++,bk[num2[i].id]=1;
else
break;
}
}
cout<<ans;
}
I Domino(遞推)
老生常談的遞推例題。。。應該都做過原題吧
公式
f[i]=f[i-1]+f[i-2]
程式碼
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll num[10000];
int main()
{
ios::sync_with_stdio(0);
cout.tie(0);
cin.tie(0);
num[1]=1;
num[2]=2;
for(int i=3;i<=1000;i++)
num[i]=num[i-1]%1000000007+num[i-2]%1000000007,num[i]%=1000000007;
ll n;
cin>>n;
cout<<num[n];
}
J Block(不明)
待填坑
K Ring(不明)
待填坑
L StringII(思維)
總共四種情況
①如果上面的字串中的字元小於下面的那麼Impossible
②如果兩個字串長度相等,且不滿足①那麼Alice
③如果上面的字串比下面的字串長,且按順序包含下面的那麼Bob
④在③的條件上如果不按順序包含那麼就是Both
程式碼
#include <bits/stdc++.h>
using namespace std;
int bk1[300];
int bk2[300];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
string a,b;
int t;
cin>>t;
while(t--)
{
int f=0;
memset(bk1,0,sizeof(bk1));
memset(bk2,0,sizeof(bk2));
cin>>a>>b;
for(int i=0;i<a.size();i++)
bk1[a[i]-'a']++;
for(int i=0;i<b.size();i++)
bk2[b[i]-'a']++;
for(int i=0;i<26;i++)
if(bk1[i]<bk2[i])
{
f=1;
break;
}
if(f)
{
cout<<"Impossible\n";
continue;
}
if(a.size()==b.size())
cout<<"Alice\n";
else
{
int k=0;
for(int i=0;i<a.size();i++)
if(a[i]==b[k])
k++;
if(k==b.size())
cout<<"Bob\n";
else
cout<<"Both\n";
}
}
}