2016ACM/ICPC亚洲区大连站-补题

2016ACM/ICPC亚洲区大连站-补题


5971-Wrestling Match

题目隐藏条件:除去已经知道的好人和坏人,如果剩余的人恰好被分成两组,即便不知道这两组哪组是好人,也是输出YES

做法:dfs染色,如果没有起点,需要随意取一个起点并随机赋予颜色(这个起点只能取一个)

代码

const int maxn=2e3+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
int n,m,x,y,u,v,col[maxn],flag;
vector<int> G[maxn];
void dfs(int x)
{
    repp(i,0,G[x].size())
    {
        int v=G[x][i];
        if (col[v]!=-1)
        {
            if (col[v]!=1-col[x])flag=0;
        }
        else
        {
            col[v]=1-col[x];
            dfs(v);
        }
    }
}
int main()
{
    while(~scanf("%d%d%d%d",&n,&m,&x,&y))
    {
        flag=1;
        rep(i,1,n)col[i]=-1,G[i].clear();
        rep(i,1,m)
        {
            scanf("%d%d",&u,&v);
            G[u].pb(v);
            G[v].pb(u);
        }
        rep(i,1,x)scanf("%d",&u),col[u]=1;
        rep(i,1,y)scanf("%d",&u),col[u]=0;
        rep(i,1,n)if (col[i]!=-1)dfs(i);
        rep(i,1,n)
        {
            if (col[i]==-1)
            {
                col[i]=0;
                dfs(i);
                break;
            }
        }
        rep(i,1,n)if (col[i]==-1)flag=0;
        if (flag)printf("YES\n");
        else printf("NO\n");    
    }
    return 0;
}



5974-A Simple Math Problem

做法
假设 x = p 1 a 1 p 2 a 2 . . . p n a n x=p_1^{a_1}p_2^{a_2}...p_n^{a_n} x=p1a1p2a2...pnan
y = p 2 b 2 p 3 b 3 . . . p m b m y=p_2^{b_2}p_3^{b_3}...p_m^{b_m} y=p2b2p3b3...pmbm
g c d ( x , y ) = p 2 m i n ( a 2 , b 2 ) gcd(x,y)=p_2^{min(a_2,b_2)} gcd(x,y)=p2min(a2,b2)
x + y = a x+y=a x+y=a
x y g c d ( x , y ) = b {xy\over gcd(x,y)}=b gcd(x,y)xy=b

对于 a a a m i n ( a 2 , b 2 ) ≤ p 2 min(a_2,b_2)\leq p_2 min(a2,b2)p2的次方
对于 b b b m i n ( a 2 , b 2 ) = p 2 min(a_2,b_2)= p_2 min(a2,b2)=p2的次方
g c d ( a , b ) = g c d ( x , y ) = p 2 m i n ( a 2 , b 2 ) gcd(a,b)=gcd(x,y)=p_2^{min(a_2,b_2)} gcd(a,b)=gcd(x,y)=p2min(a2,b2)

解一个一元二次方程即可
PS:这题目比较SB,输出答案必须小的在前大的在后

代码

const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
ll a,b,g,dt,x,x1,x2,y1,y2;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int main()
{
    while(~scanf("%lld%lld",&a,&b))
    {
        g=gcd(a,b);
        dt=a*a-4*b*g;
        x=sqrt(dt);
        if (dt<0||x*x!=dt)
        {
            printf("No Solution\n");
            continue;
        }
        x1=(a+x)/2;x2=(a-x)/2;
        y1=a-x1;y2=a-x2;
        if (x1*y1==b*g&&(a+x)%2==0)printf("%lld %lld\n",min(x1,y1),max(x1,y1));
        else if (x2*y2==b*g&&(a-x)%2==0)printf("%lld %lld\n",min(x2,y2),max(x2,y2));
        else printf("No Solution\n");
    }
    return 0;
}



5976-Detachment

做法
1.瞎列几组数据,发现尽可能的把数字拆的越多越好(除了拆成1之外)
2.拆出来的越平均越好

那么假设拆成2,3,4,…n的序列
根据平均的思想,将多余的数字均分给较大的数,从右往左分(贪心)

用乘法前缀和二分即可

证明不会,借鉴别人的博客

https://blog.csdn.net/qq_34374664/article/details/53466435

代码

const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
const ll mod=1e9+7;
ll t,x,sum[maxn],mul[maxn],ans;
ll qpow(ll a,ll b){ll res=1;while(b){if (b&1)res=res*a%mod;a=a*a%mod;b>>=1;}return res;}
ll pre(ll l,ll r){return mul[r-1]*qpow(mul[l-2],mod-2)%mod;}
int main()
{
    sum[0]=0;
    mul[0]=1;
    for (int i=1;i<=100000;i++)
    {
        sum[i]=sum[i-1]+(i+1);
        mul[i]=mul[i-1]*(i+1)%mod;
    }
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&x);
        if (x<=4)
        {
            WW(x);
            continue;
        }
        ll pos=upper_bound(sum+1,sum+1+100000,x)-sum-1;
        ll res=x-sum[pos];
        if (res==pos+1)ans=pre(3,pos+1)*(pos+3)%mod;
        else ans=pre(2,pos-res+1)*pre(pos-res+3,pos+2)%mod;
        WW(ans);
    }
    return 0;
}



5978-To begin or not to begin

做法:假设一共有 i i i个球(一个为红球)
d p 1 [ i ] dp1[i] dp1[i]表示先手赢的概率, d p 2 [ i ] dp2[i] dp2[i]表示后手赢的概率

那么可以得到以下关系式:
d p 1 [ i ] + d p 2 [ i ] = 1 dp1[i]+dp2[i]=1 dp1[i]+dp2[i]=1
d p 2 [ i ] = 1 i ∗ 0 + i − 1 i d p 1 [ i − 1 ] dp2[i]= {1\over i}*0+{i-1\over i}dp1[i-1] dp2[i]=i10+ii1dp1[i1]
d p 1 [ 1 ] = 1 dp1[1]=1 dp1[1]=1 d p 2 [ 1 ] = 0 dp2[1]=0 dp2[1]=0

递推式和第一项有了 直接O(k)解

代码

const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
const double eps=1e-7;
int k;
double dp1[maxn],dp2[maxn];
int main()
{
    dp1[1]=1.0;
    dp2[1]=0.0;
    for (double i=2;100000-i>eps;i+=1.0)
    {
        dp2[int(i)]=(i-1)/i*(dp1[int(i)-1]);
        dp1[int(i)]=1-dp2[int(i)];
    }
    while(~scanf("%d",&k))
    {
        if (fabs(dp1[k+1]-dp2[k+1])<eps)W(0);
        else if (dp1[k+1]>dp2[k+1])W(1);
        else W(2);
    }
    return 0;
}



5979-Convex

SB题
三角函数算面积




5980-Find Small A

SB题

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值