zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第九场)

    B.Quadratic equation(二次剩余)

    •题意

    给定$p=1000000007$

    有两个数x,y,其中$xleqslant y leqslant p$

    $x + y equiv b(mod  p)$
    $x imes y equiv c (mod p)$

    求 x,y的值

    •先行知识

    二次剩余

    [1]二次剩余参考资料1

    [2]二次剩余参考资料2

    •思路

    知道 $x+y$ 和 $ x imes y $

    那计算x,y 自然是$  (  x-y )^{^{2}} = (  x+y )^{^{2}} - 4xy = b^{2}-4c $ 

    设$b^{2}-4c = d$,利用二次剩余求解

    egin{cases}
    1,&d^{frac{p-1}{2}} ext{在模$p$意义下是二次剩余}\
    -1,&d^{frac{p-1}{2}} ext{在模$p$意义下是非二次剩余}\
    0,&d^{frac{p-1}{2}}equiv0pmod p
    end{cases}

    有解时:

    ①当 $d=0$ 时,两个解相等,都为$frac{b}{2}$

    ②当d是 $mod p$ 的平方剩余时有$d^{frac{p-1}{2}} equiv 1 (mod p)$ 

    设$p-1=2^{t} imes s,(2∤s)$,显然$t=1$

    所以$ (  x-y )=d^{frac{s+1}{2}}$是$(  x-y )$的一个解

    所以$x-y=d^{frac{s+1}{2}}= d^{frac{p+1}{4}}$

    由于$p=1000000007$,所以$ (p+1) mod 4 =0$可行

    因为$x-y= d^{frac{p+1}{4}}$,所以$(x - y)mod p equiv d^{frac{p+1}{4}} mod p$ 设为 a

    然后再利用 $x + y equiv b(mod  p)$

    $left { _{x + y equiv b(mod  p)}^{x - y equiv a(mod  p)} ight.$

    得到x,y

    注意 此时是在模p的情况下,

    在除以2的时候记得除法取模

    $frac{m}{n} mod p = mn^{p-2} mod p$

    •代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define p 1000000007
     5 ll qpow(ll a,ll b)
     6 {
     7     ll res=1;
     8     while(b)
     9     {
    10         if(b&1)
    11             res=res*a%p;
    12         a=a*a%p;
    13         b>>=1;
    14     }
    15     return res;
    16 }
    17 int main()
    18 {
    19 //    freopen("C:/Users/14685/Desktop/stdin&&stdout/contest","r",stdin);
    20     int t;
    21     cin>>t;
    22     while(t--)
    23     {
    24         ll b,c;
    25         cin>>b>>c;
    26         ll d=(b*b-4*c+p)%p;
    27         if(d==0)
    28             cout<<b/2<<' '<<b/2<<endl;
    29         else
    30         {
    31             ll yes=qpow(d,(p-1)/2);
    32             if(yes==1)//有解
    33             {
    34                 ll a=(qpow(d,(p+1)/4))%p;
    35                 //除法取模
    36                 ll x=(b+a)%p*qpow(2,p-2)%p%p;
    37                 ll y=((b-a)+p)%p*qpow(2,p-2)%p%p;
    38                 if(x>y)
    39                     swap(x,y);
    40                 cout<<x<<' '<<y<<endl;
    41             }
    42             else
    43                 cout<<"-1"<<' '<<"-1"<<endl;
    44         }
    45     }
    46 }
    View Code

    D.Knapsack Cryptosystem(折半枚举)

    •题意

    给出一个长度为n的集合a,

    从中选任意个数,使得这些数的和为s

    •思路

    由于长度最大为36,一共有$2^{36}$种情况

    挨个枚举肯定会TLE

    利用折半枚举,两个$2^{18}$

    •代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 map<ll,int> mp;
     5 ll a[40];
     6 int main()
     7 {
     8     int n;
     9     ll s;
    10     cin>>n>>s;
    11     int m=n/2;
    12     for(int i=0;i<n;i++)
    13         cin>>a[i];
    14 
    15     for(int i=0;i<(1<<m);i++)
    16     {
    17         ll sum1=0;
    18         for(int j=0;j<m;j++)
    19             if(i&(1<<j))//1代表选,0代表不选
    20                 sum1+=a[j];
    21         mp[sum1]=i+1;
    22     }
    23 
    24     for(int i=0;i<(1<<(n-m));i++)
    25     {
    26         ll sum2=0;
    27         for(int j=0;j<n-m;j++)
    28             if(i&(1<<j))
    29                 sum2+=a[j+m];
    30         int cnt=mp[s-sum2];
    31         if(cnt)
    32         {
    33             cnt--;
    34             for(int j=0;j<m;j++)
    35                 cout<<((cnt&(1<<j))?1:0);
    36             for(int j=0;j<n-m;j++)
    37                 cout<<((i&(1<<j))?1:0);
    38 
    39             return 0;
    40         }
    41     }
    42 }
    View Code

    E.All men are brothers(并查集+思维)

    •题意

    一开始有n个人不认识。有m个回合,他们中的两个轮流交朋友。

    朋友关系是相互的、可传递的。

    如果A是B的朋友,那么B也是A的朋友。

    例如,如果A是B的朋友,B是C的朋友,那么A和C是朋友。

    在开始和每个回合之后,请计算从中选择四个人的方法的数量,这样这四个人中的任何两个都不是朋友。

    •思路

    假设现在有5个朋友圈A,B,C,D,E

    5个朋友圈里的人数分别为a,b,c,d,e

    那么现在的方式有$(abcd+abce+abde+acbd+acde)$种

    此时令A B做朋友,也就是A B朋友圈合并

    那现在的方式有$((a+b)cde)$,也就是$(acde+bcde)$种

    减少了$(abcd+abce+abde)$,即$ab(cd+ce+de)$种

    因为$cd+ce+de=((c+d+e)^{2}-(c^{2}+d^{2}+e^{2}))/2$

    用一个$n$代表总人数,$S$记录所有集合的平和方

    可以把$(c+d+e)$看做$(n-a-b)$,把$(c^{2}+d^{2}+e^{2})$看做$(S-a^{2}+b^{2})$

    我们可以利用并查集合并、查找集合,

    由于每次时两个集合合并,a,b不合并的平方和为$a^{2}+b^{2}$

    合并后的平方和为$(a+b)^{2}=a^{2}+b^{2}+2ab$

    所以每次合并后$s+=2ab$

    注意 当所有集合都不合并时答案$ extrm{C}_{n}^{4}$可能会long long溢出,

    所以使用unsigned long long

    •代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll unsigned long long
     4 int const maxn=2e5+5;
     5 int  pre[maxn];
     6 ll num[maxn];
     7 
     8 int Find(int x)
     9 {
    10     int r=x;
    11     while(r!=pre[r])
    12         r=pre[r];
    13 
    14     int i=x,j;
    15     while(pre[i]!=r)
    16     {
    17         j=pre[i];
    18         pre[i]=r;
    19         i=j;
    20     }
    21     return r;
    22 }
    23 
    24 void mix(int x,int y)
    25 {
    26     int fx=Find(x),fy=Find(y);
    27     if(fx!=fy)
    28     {
    29         pre[fy]=fx;
    30         num[fx]+=num[fy];
    31         num[fy]=0;
    32     }
    33 }
    34 
    35 int main()
    36 {
    37     ll n,m;
    38     scanf("%lld%lld",&n,&m);
    39     for(int i=1;i<=n;i++)
    40     {
    41         pre[i]=i;
    42         num[i]=1;
    43     }
    44 
    45     ll ans=n*(n-1)/2*(n-2)/3*(n-3)/4;
    46     ll s=n;
    47     printf("%lld
    ",ans);
    48     int a,b;
    49     for(int i=1;i<=m;i++)
    50     {
    51         scanf("%d%d",&a,&b);
    52         a=Find(a),b=Find(b);
    53         if(ans==0)
    54         {
    55             puts("0");
    56             continue;
    57         }
    58         if(a==b)
    59         {
    60             printf("%lld
    ",ans);
    61             continue;
    62         }
    63         ans-=num[a]*num[b]*((n-num[a]-num[b])*(n-num[a]-num[b])-(s-num[a]*num[a]-num[b]*num[b]))/2;
    64         s+=2*num[a]*num[b];
    65         printf("%lld
    ",ans);
    66         mix(a,b);
    67     }
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    初学mysql数据库
    类与对象课堂总结
    CNN网络的基本介绍(三)
    CNN网络的基本介绍(二)
    CNN网络的基本介绍(一)
    Android studio界面布局的简单介绍
    Android studio初见及结构分析
    JDBC实现Mysqual的增删改查
    BufferedReader统计TXT文本
    JAVA的异常处理
  • 原文地址:https://www.cnblogs.com/MMMinoz/p/11364217.html
Copyright © 2011-2022 走看看