Codeforces Round #499 (Div. 2)
難得補完一次Div2,那麼過分弱雞一定要寫題解(guna)
A題
貪心,排了序從頭開始找,滿足條件能找到n個數字就OJBK
【因為如果答案裡沒包含排序後的第一個,那肯定能把答案裡的第一個位置的數值換成最小的那個,這樣的答案更小,所以正解的第一個stage一定是最小那個開始】
#include<bits/stdc++.h> using namespace std; int n,m; char st[50]; int main(){ scanf("%d%d",&n,&m); scanf("%s",st); sort(st,st+strlen(st)); int cnt=0,cntn=0,ans=0; ans=st[0];cnt=1;cntn=st[0]; for (int i=1;i<n;i++) { if (cnt==m)break; if (st[i]-cntn>=2){ ans+=st[i];cnt++;cntn=st[i]; } } if (cnt!=m)printf("-1\n"); else printf("%d\n",ans-'a'*m+m); return 0; }
B題
列舉答案,因為理論上堅持的天數最多為100(所有的食物都是同一類,m/n 最大為100)所以就不二分了
從大到小列舉答案,統計每種糧食夠多少人吃,統計的數目>=n時就找到答案了
#include<bits/stdc++.h> using namespace std; map<int,int>food; int n,m,lin; int check(int ans) { int cnt=0; if (ans==0)return 1; for (map<int,int>::iterator it=food.begin();it!=food.end();it++) cnt+=it->second/ans; if (cnt>=n)return 1; return 0; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) {scanf("%d",&lin); if (food.find(lin)==food.end())food[lin]=1; else food[lin]++; } for (int i=m/n;i>=0;i--) if (check(i)){printf("%d\n",i);break;} return 0; }
C題
數學題,設起飛或著陸後飛機重m,過程中消耗的燃油質量為y 那麼 m+y=y*a[i](或b[i]),y=m/(a[i]-1)
然後從火星到地球一路倒著推回去就行了,因為分母裡有a[i]-1,所以輸入時看下有沒有a[i]=1的,如果有就無解
#include<bits/stdc++.h> using namespace std; int n,w,a[1009],b[1009]; int main() { scanf("%d",&n); scanf("%d",&w); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); if (a[i]==1){printf("-1\n");return 0;}} for (int i=1;i<=n;i++) { scanf("%d",&b[i]); if (b[i]==1){printf("-1\n");return 0;}} double weight=double(w); weight+=weight/(double(b[1])-1.0); weight+=weight/(double(a[n])-1.0); for (int i=n;i>1;i--) { weight+=weight/(double(b[i]-1.0)); //從上個星球起飛所以是i-1 細節要注意 weight+=weight/(double(a[i-1]-1.0)); } weight-=double(w); printf("%.10lf\n",weight); return 0; }
D題
互動題。。。。開始前半小時看了下,只要注意每次輸出後要有換行符以及輸出語句後要加個fflush(stdout);語句就行了(c++)
首先問n個1,如果回覆為0那就直接退出程式就OK了,不然返回的值就是說謊序列d(因為要猜的數不可能比1小)
之後二分就完了
#include<bits/stdc++.h>
using namespace std;
int f[33],m,n,ans;
int main(){
scanf("%d%d",&m,&n);
for (int i=1;i<=n;i++)
{ printf("1\n");
fflush(stdout);
scanf("%d",&ans);
if (ans==0) return 0;
f[i]=ans;
}
int l = 1, r = m ,mid;
int cnt=0;
while (l != r) {
int mid = (l + r + 1) / 2;
printf("%d\n", mid);
fflush(stdout);
cnt++; if (cnt>n)cnt-=n;
scanf("%d",&ans);
if (ans==0)return 0;
if (ans*f[cnt]== -1)
r = mid - 1;
else
l = mid;
}
return 0;
}
E題
題意給你n個數,可以自由組合看能搞出哪些數(在mod k的情況下)
先求這些數集體的最大公約數,之後所有的這些數的組合肯定是最大公約數的某個倍數,亂搞Orz
這個學到了
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int lin,n,k,g;
set<ll>ans;
ll gcd(ll a,ll b){return a!=0?gcd(b%a,a):b;}
int main()
{ scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++)
{scanf("%d",&lin);
if(i==1)g=lin%k;
else g=gcd(g,lin%k);
}
for (int i=1;i<=1000000;i++)
ans.insert((ll)i*g%k);
printf("%d\n",ans.size());
for (set<ll>::iterator it=ans.begin();it!=ans.end();it++)
if (it==ans.begin())printf("%d",*it);
else printf(" %d",*it);
return 0;
}
F題
記憶化搜尋,每個樹節點記錄一個change值,=0意味著這個點上的值變了對output沒影響,=1有影響,=-1表示初值還沒求
搜尋的時候對於點i,如果已知change的值,那就直接能算output,不然看該改變對父節點值有沒有影響,如果沒有那麼該點的change值就為0,不然再看父節點,父節點已知change值就可以判斷output,否則再判斷父節點值改變能不能改變父父節點的值。。。。。。
就這樣搜下去
通過記錄change的值來減少時間複雜度
#include<bits/stdc++.h>
using namespace std;
struct node{
int val;
int l,r,f,change;
char t;
node(){
val=l=r=f=-1;
t='+';
change=-1;
}
}tree[1000009];
int n,lin,a[1000009];
//最開始用來求初始狀態每個節點的值
int qiu(int wei)
{
if (tree[wei].val!=-1)return tree[wei].val;
int l=tree[wei].l,r=tree[wei].r;
if (tree[wei].t=='N')
tree[wei].val=qiu(l)^1;
else
if (tree[wei].t=='A')
tree[wei].val=qiu(l)&qiu(r);
else
if (tree[wei].t=='O')
tree[wei].val=qiu(l)|qiu(r);
else
if (tree[wei].t=='X')
tree[wei].val=qiu(l)^qiu(r);
return tree[wei].val;
}
//返回wei節點的change值
int chu(int wei)
{ if (tree[wei].change!=-1)return tree[wei].change;
int ben=tree[wei].val^1,lin;
int fa=tree[wei].f;
int fv=tree[fa].val;
if (tree[fa].t=='N'){tree[wei].change=chu(fa); return tree[wei].change;}
if (tree[fa].l==wei)
lin=tree[tree[fa].r].val;
else
lin=tree[tree[fa].l].val;
if (tree[fa].t=='A')
{
if ((ben&lin)==fv){tree[wei].change=0; return tree[wei].change;}
}
else
if (tree[fa].t=='O')
{
if ((ben|lin)==fv){tree[wei].change=0; return tree[wei].change;}
}
else
if (tree[fa].t=='X')
{
if ((ben^lin)==fv){tree[wei].change=0; return tree[wei].change;}
}
tree[wei].change=chu(fa); return tree[wei].change;
}
char st[10];
int main(){
scanf("%d",&n);a[0]=0;
for (int i=1;i<=n;i++){
scanf("%s %d",st,&lin);tree[i].t=st[0];
if (st[0]!='I'&&st[0]!='N'){
tree[i].l=lin;scanf("%d",&tree[i].r);
tree[tree[i].l].f=i;
tree[tree[i].r].f=i;
}
else if (st[0]=='I') {tree[i].val=lin;a[0]++;a[a[0]]=i;}
else {
tree[i].l=lin;
tree[lin].f=i;
}
}
qiu(1);tree[1].change=1;
for (int i=1;i<=a[0];i++)
{
if (chu(a[i]))printf("%d",tree[1].val^1);
else printf("%d",tree[1].val);
}
return 0;
}