早上开幕式没来得及看,来到机房惊奇地发现:
我 又 柯 以 水 一 场 比 赛 了 ! q w q \red{我又柯以水一场比赛了!qwq} 我又柯以水一场比赛了!qwq
T 1 : T1: T1: P 2296 [ N O I P 2014 提 高 组 ] 寻 找 道 路 P2296 [NOIP2014 提高组] 寻找道路 P2296[NOIP2014提高组]寻找道路
期望得分: 100 p t s 100pts 100pts
实际得分: 90 p t s 90pts 90pts
思路:
拿到题目发现是我最近经常打的图论题,题目很简洁没有什么复杂难懂的背景。题意大概是求一道对路径节点有要求的最短路问题。对于最短路上的点连接的所有点必须直接或间接的与终点联通这问题,当时立马想到了建反图,以终点为起始点进行 d f s dfs dfs,没有搜到的点即为无法到达的点,打上 t a g tag tag.然后再遍历结点数组对打上 t a g tag tag的点所连接的所有点再次打上 t a g tag tag。
由于图的边不带权,直接 b f s bfs bfs,打上 t a g tag tag的点直接忽视,求出最短路径即可。
复杂度为 Θ ( N ) \Theta(N) Θ(N), 3 m i n 3min 3min出思路, 10 m i n 10min 10min出代码。 3 m s 3ms 3ms稳稳地过。
可是却 R E \purple{RE} RE了一个点? q w q q w q qwqqwq qwqqwq
C u t e C o d e : \pink{Cute\space Code:} Cute Code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4;
int n,m,s,t;
int v[maxn],is[maxn],d[maxn],tag[maxn];
vector<int> ver[maxn],fver[maxn];
inline void read()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
ver[u].push_back(v);
fver[v].push_back(u);
}
cin>>s>>t;
}
inline void work(int x)
{
if(!fver[x].size())
{
return;
}
for(int y=0;y<fver[x].size();y++)
{
int t=fver[x][y];
if(!v[t])
{
v[t]=1;
is[t]=1;
work(t);
}
}
}
inline void make_tag()
{
for(int i=1;i<=n;i++)
{
if(!is[i])
{
for(int j=0;j<fver[i].size();j++)
{
tag[fver[i][j]]=0;
}
}
}
}
inline void bfs()
{
memset(v,0,sizeof(v));
queue<int> q;
d[s]=0;
q.push(s);
while(q.size())
{
int x=q.front();q.pop();
for(int y=0;y<ver[x].size();y++)
{
int t=ver[x][y];
if(!v[t]&&tag[t])
{
v[t]=1;
d[t]=d[x]+1;
q.push(t);
}
}
}
}
int main()
{
memset(tag,1,sizeof(tag));
read();
is[t]=1;
work(t);
make_tag();
bfs();
if(d[t])
cout<<d[t]<<endl;
else cout<<-1<<endl;
return 0;
}
T 2 : P 1080 [ N O I P 2012 提 高 组 ] 国 王 游 戏 T2:P1080 [NOIP2012 提高组] 国王游戏 T2:P1080[NOIP2012提高组]国王游戏
期望得分: 100 p t s 100pts 100pts
实际得分: 90 p t s 90pts 90pts,怎么又是90pts了
解题思路:
一道很有趣的数学题,用到了贪心的思想.题目意思为给你两个正整数数列
{ a i } \{a_i\} {
ai}和 { b i } ; i ∈ [ 1 , n ] \{b_i\};i\in[1,n] {
bi};i∈[1,n],你可以随意交换每组元素的位置 ( a i , b i ) (a_i,b_i) (ai,bi),但 ( a 1 , b 1 ) (a_1,b_1) (a1,b1)不能动。使得下面这个函数:
f ( x ) = ∏ i = 1 x − 1 a i b x , x ∈ [ 2 , n ] f(x)=\frac{\prod\limits_{i=1}^{x-1}a_i}{b_x},x\in[2,n] f(x)=bxi=1∏x−1ai,x∈[2,n]
的最大值最小。
贪心策略是以 a i × b i a_i\times b_i ai×bi为基准将 ( a i , b i ) (a_i,b_i) (ai,bi)升序排列。可以用组合数学中的微扰法证明。
考虑到数据范围,要开高精。
感 觉 至 少 应 该 是 蓝 题 q w q , 怎 么 就 绿 了 q w q 感觉至少应该是\blue{蓝题}qwq,怎么就\green{绿}了qwq 感觉至少应该是蓝题qwq,怎么就绿了qwq
A C → 90 p t s c o d e AC\to 90pts\space code AC→90pts code
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
struct Wint:vector<int>
{
Wint(int n=0)
{
push_back(n);
check();
}
Wint& check()
{
while(!empty()&&!back())pop_back();
if(empty())return *this;
for(int i=1; i<size(); ++i)
{
(*this)[i]+=(*this)[i-1]/10;
(*this)[i-1]%=10;
}
while(back()>=10)
{
push_back(back()/10);
(*this)[size()-2]%=10;
}
return *this;
}
};
istream& operator>>(istream &is,Wint &n)
{
string s;
is>>s;
n.clear();
for(int i=s.size()-1; i>=0; --i)n.push_back(s[i]-'0');
return is;
}
ostream& operator<<(ostream &os,const Wint &n)
{
if(n.empty())os<<0;
for(int i=n.size()-1; i>=0; --i)os<<n[i];
return os;
}
bool operator!=(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return 1;
for(int i=a.size()-1; i>=0; --i)
if(a[i]!=b[i])return 1;
return 0;
}
bool operator==(const Wint &a,const Wint &b)
{
return !(a!=b);
}
bool operator<(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return a.size()<b.size();
for(int i=a.size()-1; i>=0; --i)
if(a[i]!=b[i])return a[i]<b[i];
return 0;
}
bool operator>(const Wint &a,const Wint &b)
{
return b<a;
}
bool operator<=(const Wint &a,const Wint &b)
{
return !(a>b);
}
bool operator>=(const Wint &a,const Wint &b)
{
return !(a<b);
}
Wint& operator+=(Wint &a,const Wint &b)
{
if(a.size()<b.size())a.resize(b.size());
for(int i=0; i!=b.size(); ++i)a[i]+=b[i];
return a.check();
}
Wint operator+(Wint a,const Wint &b)
{
return a+=b;
}
Wint& operator-=(Wint &a,Wint b)
{
if(a<b)swap(a,b);
for(int i=0; i!=b.size(); a[i]-=b[i],++i)
if(a[i]<b[i])
{
int j=i+1;
while(!a[j])++j;
while(j>i)
{
--a[j];
a[--j]+=10;
}
}
return a.check();
}
Wint operator-(Wint a,const Wint &b)
{
return a-=b;
}
Wint operator*(const Wint &a,const Wint &b)
{
Wint n;
n.assign(a.size()+b.size()-1,0);
for(int i=0; i!=a.size(); ++i)
for(int j=0; j!=b.size(); ++j)
n[i+j]+=a[i]*b[j];
return n.check();
}
Wint& operator*=(Wint &a,const Wint &b)
{
return a=a*b;
}
Wint divmod(Wint &a,const Wint &b)
{
Wint ans;
for(int t=a.size()-b.size(); a>=b; --t)
{
Wint d;
d.assign(t+1,0);
d.back()=1;
Wint c=b*d;
while(a>=c)
{
a-=c;
ans+=d;
}
}
return ans;
}
Wint operator/(Wint a,const Wint &b)
{
return divmod(a,b);
}
Wint& operator/=(Wint &a,const Wint &b)
{
return a=a/b;
}
Wint& operator%=(Wint &a,const Wint &b)
{
divmod(a,b);
return a;
}
Wint operator%(Wint a,const Wint &b)
{
return a%=b;
}
Wint pow(const Wint &n,const Wint &k)
{
if(k.empty())return 1;
if(k==2)return n*n;
if(k.back()%2)return n*pow(n,k-1);
return pow(pow(n,k/2),2);
}
struct element
{
Wint l;
Wint r;
};element ele[10005];
inline bool cmp(element a,element b)
{
return (a.l*a.r)<(b.l*b.r);
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n+1;i++)
{
Wint l,r;
cin>>l>>r;
ele[i].l=l;ele[i].r=r;
}
sort(ele+2,ele+n+2,cmp);
//for(int i=1;i<=n+1;i++) cout<<i<<":"<<ele[i].l<<" "<<ele[i].r<<endl;
Wint ans=1;
for(int i=1;i<=n;i++)
{
ans=ans*ele[i].l;
}
cout<<ans/ele[n+1].r<<endl;
}