上周日做了一个——
疯狂的8小时耐力赛
……Codeforces的 Round #79 ~ #84……
这次就不放题了,传送门:http://vjudge.net/contest/view.action?cid=51127#overview
把过了的题贴一贴做个总结好了……
Problem A CodeForces 102A Clothes
这个题是单向图内想找三个元素组成的环,我是不会图论的所以不用担心我肯定不会用图论的什么高端技巧弄出来的……
事先用vector来记录每个服饰搭配的服饰们(方便找),读入完毕之后,我们从头向尾遍历,为了剪枝,我们第一个向第二个的方向一定是index从小向大,当然第二个向第三个不可以再这样了,否则无法全部遍历完。
当选定了第一个——在第一个的搭配服饰中遍历选中第二个——在第二个的搭配服饰中遍历选中第三个——如果第三个的搭配服饰中有第一个——三个价格之和update
遍历完毕即可。
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define update(a) ans=(ans==-1?a:ans>a?a:ans)
using namespace std;
int price[10001];
int match[101][101];
vector<int> v[101];
int main()
{
int N,M,ans=-1;
cin>>N>>M;
memset(price,0,sizeof price);
memset(match,0,sizeof match);
for(int i=0;i<101;i++) v[i].clear();
for(int i=1;i<=N;i++)
{
int tmp;
cin>>tmp;
price[i]=tmp;
}
for(int j=1;j<=M;j++)
{
int a,b;
cin>>a>>b;
match[a][b]=match[b][a]=1;
v[a].push_back(b);
v[b].push_back(a);
}
for(int i=1;i<=N-1;i++) //I am 1st point
{
for(int j=0;j<v[i].size();j++) //I am 2nd point
{
int k=v[i].at(j);
if(k<j)continue;
else
{
for(int l=0;l<v[k].size();l++)
{
int m=v[k].at(l);
for(int n=0;n<v[m].size();n++)
{
int o=v[m].at(n);
if(o==i) update(price[i]+price[k]+price[m]);
//cout<<i<<' '<<k<<' '<<m<<endl;
}
}
}
}
}
cout<<ans<<endl;
return 0;
}
Problem B CodeForces 102B Sum of Digits
这个题目是给一个数,问它的各位数字之和的各位数字之和的……各位数字之和(到只剩一位为止)是多少
模拟即可,反正即便数字全都是9也不会有很多次就结束了
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int anscnt=0;
int sums(string s)
{
anscnt++;
int cnt=0;
for(int i=0;i<s.length();i++)
{
cnt+= s[i]-'0';
}
return cnt;
}
int onedigit (int x)
{
if(x/10==0) return x;
else
{
anscnt++;
int xnxt=0,xtmp=x;
while(xtmp)
{
xnxt+= xtmp%10;
xtmp/= 10;
}
return onedigit(xnxt);
}
}
int main()
{
string s; cin>>s;
if(s.length()!=1)
{
int x=sums(s);
int ans=onedigit(x);
}
cout<<anscnt;
return 0;
}
Problem C CodeForces 102C Homework
小明想偷工减料少写点作业,然后给了一个字符串,小明想选择性少写其中的某几种字符,但是少写的个数不能超过k个字,问最终最少剩下多少种字符并输出剩下的字符串。
读入的时候用一个26字母数组记录每个字母出现的次数然后排序,之后贪心就好啦~从出现次数最少的开始去掉(要求剩下种类最少那就是要去掉最多种字符),直到超过k为止(当然超过的时候的那种不能去掉),去掉的那种字母记得要把出现次数置为0.
然后过一遍原字符串,每遇到一个出现次数非零的就输出并把出现次数减一,这样输出的就是正确结果啦o(^▽^)o。
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
priority_queue <pii> pq;
int n,k,kind=0,wcnt[26],mrk[26];
pii chr[26];
string s;
void init()
{
memset(wcnt,0,sizeof wcnt);
memset(mrk,0,sizeof mrk);
memset(chr,0,sizeof chr);
for(int i=0;i<n;i++)
{
if(wcnt[s[i]-'a']==0)kind++;
wcnt[s[i]-'a']++;
}
for(int i=0;i<26;i++)
{
pq.push(make_pair(wcnt[i],i));
}
}
void print()
{
cout<<kind<<endl;
for(int i=0;i<n;i++)
{
if(wcnt[s[i]-'a']!=0)
{
cout<< s[i];
wcnt[s[i]-'a']--;
}
}
}
void solve()
{
for(int i=0;i<26;i++)
{
chr[i]=pq.top();
pq.pop();
//cout<<chr[i].first<<" "<<chr[i].second<<endl;
}
for(int i=25;i>=0;i--)
{
int numb=chr[i].first;
if(numb==0)continue;
if(k-numb<0)break;
else
{
//cout<<"del:"<<chr[i].first<<endl;
k-=numb;
chr[i].first=0;
wcnt[chr[i].second]=0;
kind--;
}
}
}
void test()
{
cout<<"---------------------"<<endl;
for(int i=0;i<26;i++)
{
cout<<chr[i].first<<"\t"<<chr[i].second<<endl;
}
}
int main()
{
cin>>s; n=s.length();
cin>>k; init();
//cout<<n<<endl;
if(k>=n)
{
cout<<"0"<<endl;
return 0;
}
else if(k==0)
{
cout<<kind<<endl;
cout<<s;
return 0;
}
solve();
print();
return 0;
}
Problem F CodeForces 104A Blackjack
(●'◡'●)打表过的 嘿嘿~ 读题快的好处~
给你一堆牌,已经拿出了一张黑桃Q,问再拿出一张之后能凑到这么多分,有多少种可能。
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int ans[]={0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,15,4,0,0,0,0,0};
int main()
{
int n; cin>>n;
cout<<ans[n];
return 0;
}
Problem G CodeForces 104B Testing Pants for Sadness
看到题目我就被吓到了……为了悲伤测胖次是怎么一回事= =
Print a single number — the minimal number of clicks needed to pass the test it the worst-case scenario。
看懂题之后大概就是个求和问题了
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 ll;
ll a[105];
int main()
{
int i,n;
while(scanf("%d",&n)!=EOF)
{
ll sum=0;
for(i=1;i<=n;i++) cin>>a[i];
for(i=1;i<=n;i++) sum+=i*(a[i]-1)+1;
cout<<sum;
}
return 0;
}
Problem K CodeForces 106A Card Game
桌上两张牌让你帮忙比大小,首先告诉你有种花色叫做王牌。王牌一定秒杀非王牌,如果两个都是王牌或者两个都不是的话就比点数大小。
水模拟:
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
string tin,fst,snd;
//char suit[4]={'S','H','D','C'};
//char rank[9]={'6','7','8','9','T','J','Q','K','A'};
int main()
{
string s,s1,s2;
int i,pos1,pos2;
char a[10]="6789TJQKA";
cin>>s>>s1>>s2;
if(s1[1]==s[0])
{
if(s2[1]==s[0])
{
for(i=0;i<9;i++)
{
if(s1[0]==a[i]) pos1=i;
if(s2[0]==a[i]) pos2=i;
}
if(pos1<=pos2) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
else cout<<"YES"<<endl;
}
else
{
if(s1[1]==s2[1])
{
for(i=0;i<9;i++)
{
if(s1[0]==a[i]) pos1=i;
if(s2[0]==a[i]) pos2=i;
}
if(pos1<=pos2) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
else cout<<"NO"<<endl;
}
return 0;
}
Problem L CodeForces 106B Choosing Laptop
选笔记本,如果有一种笔记本比另一种各项性能都要高(价格除外),那么那个全面低下的就叫做过时了。
问所有没有过时的笔记本中最便宜的是哪个。
别被吓到了后面那个是注释掉的部分……原先想用队列然后一次一次O(nlogn)的清理掉所有的过时电脑后来不知为何老是wa……
然后就暴力了。
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
//Why not trying force^
using namespace std;
int x[103][4];
int main(){
int n,i,j,min=1001,index; cin>>n;
for(i=0;i<n;i++)
scanf("%d %d %d %d",&x[i][0],&x[i][1],&x[i][2],&x[i][3]);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if((x[j][0]<x[i][0])&&(x[j][1]<x[i][1])&&(x[j][2]<x[i][2]))
x[j][3]=1000+1;//goto back
for(i=0;i<n;i++) if(x[i][3]<min){min=x[i][3];index=i+1;}
cout<<index<<endl;
}
/*****************Unlimited Loop**********************
#define S first.first
#define R first.second
#define H second.first
#define C second.second
#define CPT(s,r,h,c) make_pair(make_pair(s,r),make_pair(h,c))
using namespace std;
int cost[101];
typedef pair<int,int> pii;
vector < pair<pii,pii> > v;
int main()
{
memset(cost,0,sizeof cost);
priority_queue < pair<pii,pii> > pq;
while(!pq.empty())pq.pop();
int n; cin>>n;
for(int i=0;i<n;i++)
{
int s,r,h,c; cin>>s>>r>>h>>c;
pq.push(CPT(s,r,h,i+1));
cost[i+1]=c;
}
queue < pair<pii,pii> > q;
while(!q.empty())q.pop();
while(!pq.empty())
{
q.push(pq.top());
pq.pop();
}
while(!q.empty())
{
pair<pii,pii> last=q.front();pq.pop();
v.push_back(last);
for(int i=0;i<n;i++)
{
pair<pii,pii> now=q.front();q.pop();
if(now.S<last.S &&now.R<last.R &&now.H<last.H);
else q.push(now);
}
}
int minc=9999,index=-1;
for(int i=0;i<v.size();i++)
{
if(minc>v.at(i).C)
{
minc=cost[v.at(i).C];
index=v.at(i).C;
}
}
cout<<minc;
return 0;
}
**********************************************************/
Problem P CodeForces 108A Palindromic Times
打表~~~ 给你当前时间,问你下一个对称的时间是啥时候
这道题有个坑了好些人的地方就是,别忘了00:00,不管是开头还是结尾,23:59后是 00:00
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int hor[]={0, 1, 2, 3, 4, 5,10,11,12,13,14,15,20,21,22,23};
int mie[]={0,10,20,30,40,50,1 ,11,21,31,41,51, 2,12,22,32};
int main()
{
char maohao;
int h,m;
cin>>h>>maohao>>m;
for(int i=0;i<16;i++)
{
if((hor[i]==h && mie[i]>m) || hor[i]>h)
{
if(hor[i]<10)cout<<"0";
cout<<hor[i]<<":";
if(mie[i]<10)cout<<"0";
cout<<mie[i]<<endl;
return 0;
}
}
cout<<"00:00"<<endl;
return 0;
}
Problem Q CodeForces 108B Datatypes
这是一道我一直以为我做不出的题Q^Q,后来快结束了我发现我勒个去要不要这么简单……
就是问你一个集合内有若干个数,小的数乘二(bit的乘方就是需要2倍的存放空间)不能比大的数大
——题意转换:问有一个集合里面有一堆可以重复的数,问这个集合是否存在两个不同的数,小的数乘以二比大的数大
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int a[100001];
int main()
{
int n; cin>>n;
memset(a,0,sizeof a);
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
for(int i=1;i<n;i++)
{
if(a[i]==a[i-1])continue;
if(a[i]<a[i-1]*2)
{
cout<<"YES"<<endl;
return 0;
}
}
cout<<"NO"<<endl;
return 0;
}
Problem R CodeForces 108C Dorm Water Supply
这这这这这,明知道我不会图论就给我又送了一个伪图论咩哈哈哈~
这道题是说,每个寝室最多只能有一个接入的水管,最多只能有一个接出的水管。然后寝室间各种连水管,问你连完了之后有多少个水管链,请输出水管头和水管尾,并告知这个水管链能输的水(就是中间这么多水管的最小流量)。特别的:如果形成了环我们就不要它了。
于是^_^ deque啊list啊各种闹腾~
对于每个abd:
1)a和某链尾巴一样,b加入那个链 push_back b
2)b和某链头一样,a加入那个链 push_front a
3)没人要,先后给一个空链push_back进a,b
4)维护维护
over~ 下面第一段代码是ac代码,第二段比较好懂我这道题的算法意思,可惜……是wa的……(抱歉看了太久没发现错,但是只看关键思想就好,恩恩,别拿那个错的去提交哦,告诉你wa在第四组测试数据上~)
#include <list>
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
struct Node
{
int in, out;
int dout; //diameter
Node () {in = -1, out = -1;}
};
pii pr;
int n, p;
int a, b, d;
Node v[1001];
vector <int> from, to, vol;
int cmp(const void *a, const void *b)
{
return (*(int *)b-*(int *)a);
}
pii dfs(int i, int w)
{
if (v[i].out == -1)
return make_pair(i, w);
return dfs(v[i].out, min(w, v[i].dout));
}
int main()
{
cin>>n>>p;
for(int i = 0; i < p; i++)
{
cin>>a>>b>>d;
v[b].in = a;
v[a].out = b;
v[a].dout = d;
}
for (int i = 1; i <= n; i++)
if (v[i].in == -1 && v[i].out != -1)
{
from.push_back(i);
pr=dfs(i, v[i].dout);
to.push_back(pr.first);
vol.push_back(pr.second);
}
int vols=(int)vol.size(); cout<<vols<<endl;
for (int i = 0; i < vols; i++) cout<<from[i]<<" "<<to[i]<<" "<<vol[i]<<endl;
return 0;
}
#include <list>
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
int num=0,ansnum=0;
int dia[501],sup[501];
list<int> v[501];
int cmp(const void *a, const void *b)
{
return (*(int *)b-*(int *)a);
}
int main()
{
memset(dia,0,sizeof dia);
memset(sup,0,sizeof sup);
for(int i=0;i<501;i++) v[i].clear();
int n,p; cin>>n>>p;
for(int i=0;i<p;i++)
{
int a,b,d,flag=0; cin>>a>>b>>d;
for(int j=0;j<=num;j++)
if(v[j].front()==b||v[j].back()==a)
{
flag=1;
if(v[j].front()==b)
{
v[j].push_front(a);
dia[j]= (dia[j]>d?d:dia[j]);
}
else
{
v[j].push_back(b);
dia[j]= (dia[j]>d?d:dia[j]);
}
}
if(!flag)
{
v[num].push_back(a);
v[num].push_back(b);
dia[num]=d;
num++;
}
}
//cout<<num<<endl;
ansnum=0;
priority_queue < pair<int,pii>,vector<pair<int,pii> >,greater<pair<int,pii> > > pq;
while(!pq.empty())pq.pop();
for(int i=0;i<num;i++)
{
if(v[i].front()==v[i].back())
{
dia[i]=-1;
}
else
{
pq.push(make_pair(v[i].front(),make_pair(v[i].back(),dia[i])));
ansnum++;
}
//cout<<v[i].front()<<" "<<v[i].back()<<" "<<dia[i]<<endl;
}
cout<<ansnum<<endl;
for(int i=0;i<ansnum;i++)
{
pair<int,pii> now=pq.top();
pq.pop();
cout<<now.first<<" "<<now.second.first<<" "<<now.second.second<<endl;
}
return 0;
}
Problem U CodeForces 110A Nearly Lucky Number
差点就是幸运数……我就是没看见差点……我提交了一发【差点就是幸运数】+【幸运数】的上去wa了……
其实交一个【差点就是幸运数】就对了Q^Q
【差点就是幸运数】概念:数字中4、7的个数为全部由4、7组成的数。
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
bool islucky(int n)
{
while(n)
{
int t=n%10;
if(t==4 || t==7) n/=10;
else return false;
}
return true;
}
int main()
{
int num=0;
string s; cin>>s;
for(int i=0;i<s.length();i++)
{
if(s[i]=='4'||s[i]=='7')num++;
}
//cout<<num<<endl;
if(!num)cout<<"NO"<<endl;
else cout<< (islucky(num)?"YES" :"NO") <<endl;
return 0;
}
Problem V CodeForces 110B Lucky String
这个题要求输出长度为n的最小幸运字符串,仔细理解题意在草稿纸上算算:
abcdabcd一直到底,然后处理尾巴就行
#include <cstdio>
int main()
{
int n,i;
while(~scanf("%d",&n))
{
int a=n%4 ,b=n/4;
for(i = 0; i < b; i++) printf("abcd");
for(i = 0; i < a; i++) printf("%c",i+'a');
printf("\n");
}
return 0;
}
Problem W CodeForces 110C Lucky Sum of Digits
这位哥哥你真的是C题么……
问仅仅由4和7组成的和为n的最小数为多少
首先位数要最少是首要的(当然连4、7都组成不了的就负分粗去啦),所以可以4、7互换的时候我们要7不要4
然后排列的时候4全扔前面7全扔后面即可(之前以为除28打表就行了,后来发现……似乎得调用之前的某个28拆开来换4才能组成某个数,就不打表偷懒了^_^)
/*
#include <stack>
#include <queue>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int fs [18]={0, 1, 0, 2, 1, 3, 0, 2, 4, 3, 5, 0, 2, 4, 6, 1, 3, 5};//four s
int ss [18]={0, 0, 1, 0, 1, 0, 2, 1, 0, 1, 0, 3, 2, 1, 0, 3, 2, 1};//seven s
int sup[18]={0, 4, 7, 8,11,12,14,15,16,19,20,21,22,23,24,25,26,27};
int main()
{
int n; cin>>n;
int _m=n/28,m=n%28;
int cnt4=0,cnt7=4*_m;
if(n<11)
{
if(n==4||n==7)cout<<n;
cout<<"-1";
return 0;
}
for(int i=0;i<18;i++)
{
if(m==sup[i])
{
cnt4+=fs[i];
cnt7+=ss[i];
for(int j=0;j<cnt4;j++)cout<<"4";
for(int k=0;k<cnt7;k++)cout<<"7";
return 0;
}
}
cout<<"-1";
return 0;
}
*/
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
int n,i,j,k,flag,sum;
int main()
{
int s4,s7; cin>>n;
s4=n/4; s7=n/7;
for(i=0;i<=s4;i++)
{
for(j=0;j<=s7;j++) if(i*4+j*7==n)
{
flag=1;
break;
}
if(flag) break;
}
if(!flag) cout<<-1<<endl;
else
{
for(k=1;k<=i;k++) printf("4");
for(k=1;k<=j;k++) printf("7");
printf("\n");
}
return 0;
}