eg:題目難度感覺是升序的啊,又是一場七題(然後又沒打完,跑去和同學英雄聯盟了),沒想到I題只是個小貪心,H題樹狀數組和J題確實不太會,簡單的記錄一下通過的前七道題,最後三道題如果補了的話會更新的。
A-歐幾里得
題意:輾轉相除法進行了n次,求最小的a+b且a>b。
題解:隨意觀察了一下,可以發現是個斐波那契數列從若n爲0則是0+1,若n爲1則是1+2,類推。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
ll f[100];
int main(){
f[0]=0;f[1]=1;f[2]=2;
for(int i=3;i<=81;i++)f[i]=f[i-1]+f[i-2];
int T;
scanf("%d",&T);
while(T--){
int i;
scanf("%d",&i);
printf("%lld\n",f[i]+f[i+1]);
}
return 0;
}
B-括號序列
題意:括號序列判斷是否合法。
題解:棧的基礎應用,似乎會爆系統棧(或者我係統棧寫萎了)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
char s[maxn];
char q[maxn];
int cnt;
int main(){
scanf("%s",&s);
int len=strlen(s),flag=0;
for(int i=0;i<len;i++){
if(s[i]=='(' || s[i]=='[' || s[i]=='{')q[++cnt]=s[i];
else{
if(s[i]==')'){
if(q[cnt]=='(')cnt--;
else flag=1;
}
if(s[i]==']'){
if(q[cnt]=='[')cnt--;
else flag=1;
}
if(s[i]=='}'){
if(q[cnt]=='{')cnt--;
else flag=1;
}
}
}
if(cnt!=0)flag=1;
if(!flag)puts("Yes");
else puts("No");
return 0;
}
C-子段乘積
題意:長度爲n的數組,求連續k個數的乘積的最大值。
題解:線段樹維護區間乘法。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int mod=998244353;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int n,k,a[maxn];
ll s[maxn*4];
void pushup(int node){
s[node]=s[node<<1]*s[node<<1|1]%mod;
}
void build(int node,int l,int r){
if(l==r){
s[node]=1ll*a[l];
return;
}
int mid=(l+r)>>1;
build(node<<1,l,mid);
build(node<<1|1,mid+1,r);
pushup(node);
}
ll query(int L,int R,int l,int r,int node){
if(L<=l && r<=R)return s[node];
int mid=(l+r)>>1;
ll ans=1;
if(L<=mid)ans=ans*query(L,R,l,mid,node<<1)%mod;
if(R>mid)ans=ans*query(L,R,mid+1,r,node<<1|1)%mod;
return ans;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
build(1,1,n);
int l=1,r=k;
ll ans=0;
while(r<=n){
ans=max(ans,query(l,r,1,n,1));
l++;r++;
}
printf("%lld\n",ans);
return 0;
}
D-子段異或
題意:長度爲n的數組,求區間異或和爲0的數量。
題解:維護區間前綴異或和,如果兩個異或和的值相等說明這個區間異或和爲0。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int mod=998244353;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int n,a[maxn],f[maxn];
map<int,int>mmap;
ll ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)f[i]=f[i-1]^a[i];
for(int i=0;i<=n;i++)
ans+=1ll*mmap[f[i]],mmap[f[i]]++;
printf("%lld\n",ans);
return 0;
}
E-最小表達式
題意:給出若干個1~9還有+號,問如何排列組合使得可以排列出一個合法的加法算式且結果最小。
題解:貪心,儘可能均勻分配數字即可。注意需要用到高精度。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int a[11],k,num;
char s[maxn];
string A[maxn],ans,v;
string add(string a,string b){
v.clear();
int tmp=0,t=0;
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
while(a.size()!=b.size()){
if(a.size()>b.size())b.push_back('0');
else a.push_back('0');
}
for(int i=0;i<a.size();i++){
tmp=a[i]+b[i]-'0'*2+t;
t=tmp/10;
v.push_back(tmp%10+'0');
}
if(t>0)v.push_back(t+'0');
reverse(v.begin(),v.end());
return v;
}
int main(){
scanf("%s",&s);
int len=strlen(s);
for(int i=0;i<len;i++)
if(s[i]=='+')k++;
else a[s[i]-'0']++,num++;
if(k==0){
sort(s,s+len);
printf("%s\n",s);
}
else{
int l=1;
for(int i=1;i<=9;i++){
for(int j=1;j<=a[i];j++){
A[l].push_back(i+'0');
l++;
if(l>k+1)l=1;
}
}
for(int i=1;i<=k+1;i++)
ans=add(A[i],ans);
cout<<ans<<endl;
}
return 0;
}
F-樹上博弈
題意:給出一棵樹,每次只能選擇朝葉子結點或者父親結點移動,如果不能移動則對方獲勝。問先手獲勝的雙方起始狀態數量。
題解:觀察到,如果雙方距離爲偶數時先手必勝。那麼轉換成樹上求距離爲偶數的點對。樹上dp入門題。考慮爲到u結點的偶數結點數,爲到u結點的奇數結點數,遍歷這棵樹,to表示可到達的結點,每個結點的答案就是,每次還需要更新和
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
int read(){
int f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int n;
ll dp[maxn][2],ans;
vector<int>G[maxn];
inline void dfs(int u,int fa){
dp[u][0]=1ll;dp[u][1]=0ll;
for(int i=0;i<G[u].size();i++){
int to=G[u][i];
if(to==fa)continue;
dfs(to,u);
ans+=dp[u][0]*dp[to][1];
ans+=dp[u][1]*dp[to][0];
dp[u][0]+=dp[to][1];
dp[u][1]+=dp[to][0];
}
}
int main(){
n=read();
for(int i=2;i<=n;i++){
int x;
x=read();
G[x].push_back(i);
G[i].push_back(x);
}
ans=0;
dfs(1,-1);
printf("%lld\n",ans*2ll);
return 0;
}
G-音樂鑑賞
題意:不怎麼好說,看題理解吧。
題解:二分答案,二分這個期末佔比。check僅需保證每個人的平均分乘上平均分佔比加上81*期末佔比大於90即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int n;
double ans,a[maxn];
bool check(double x){
if(ans*(1.0-x)+81*x>90)return true;
else return false;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf",&a[i]),ans+=a[i];
ans/=n;
double l=0.0,r=1.0,mid,f;
while(fabs(l-r)>=eps){
mid=(l+r)/2;
if(check(mid))l=mid,f=l;
else r=mid;
}
f*=100;
printf("%.2lf%%\n",f);
return 0;
}
剛剛補了道I題前來更新
I-匹配星星
題意:給出了n個星星,每個星星有橫縱座標還有一個價值z,如果那麼就能匹配,要儘可能多的匹配。求數量。
題解:z的取值是0和1,所以題目就成了一道水題。先按照x座標排序如果z爲0就加入待匹配序列,爲1就開始匹配,找到一個滿足題意的儘可能大的y即可。用muliset維護(STL大出彩)。
#include "stdio.h"
#include "string.h"
#include "iostream"
#include "algorithm"
#include "stack"
#include "set"
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;
int n,ans;
struct arr{
int x,y,z;
}p[maxn];
multiset<int>s;
multiset<int>::iterator it;
bool cmp(arr a,arr b){
return a.x<b.x;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
sort(p+1,p+1+n,cmp);
for(int i=1;i<=n;i++){
if(p[i].z==0)s.insert(p[i].y);
else{
it=s.lower_bound(p[i].y);
if(it!=s.begin()){
it--;
s.erase(it);ans++;
}
}
}
printf("%d\n",ans);
return 0;
}