zoukankan      html  css  js  c++  java
  • NOIP模拟21+22

    模拟21确实毒瘤。。。考场上硬刚T3 2.5h,成功爆零

    T1.数论

      看这题目就让人不想做,考场上我比较明智的打完暴力就弃掉了,没有打很久的表然后找规律。

      正解貌似是乱搞,我们考虑一个比较显然的结论:

      对于一个质数 p,我们考虑所有仅包含小于 p 的质因子的正整数集 G。不难发现:
      • 若 x ∈ G,且在 G 中已经有超过 K 个小于 x 的整数约数个数多于 x,即 x 一定不是良好的,
      则 xp^c (c ≥ 0) 也一定不可能是良好的。

      于是我们可以利用已知的良好的数筛出接下来“可能良好”的数,再在这些数里面排除,除去确定的不是良好的数,即可得到所有良好的数。

    T2.

      大概是这三道题里最水的?

      思路卡壳点:最终的答案与c的大小无关,只与c二进制位中1的个数有关。

      发现了这个结论,我们就可以很愉快的dp了。

    T3.

      我们可以采取逐位确定的方法,首先求出以每个点为根时dfs序的总方案数,接下来:

      设当前点所要对应b数列中的p位置,若当前点<b[p],那么直接累加随便走的方案数;若当前点>b[p],break;否则,p++,去当前点的子树中寻找进行同样的过程。

      说起来很容易,实际操作挺shi的,反正我调了一晚上。。。。

      1 #include<bits/stdc++.h>
      2 #define mod 1000000007
      3 #define ll long long
      4 using namespace std;
      5 int n,fi[300005],ne[600005],to[600005],b[300005],du[300005],tot,p,siz[300005],tt,sum[30000005],r[300005],lc[30000005],rc[30000005];
      6 ll f[300005],js[300005],ans,ni[300005],ff[300005],fc[300005];
      7 vector<int>h[300005];
      8 bool v[300005];
      9 inline int read(){
     10     int x=0;
     11     char ch=getchar();
     12     while(ch<'0'||ch>'9')ch=getchar();
     13     while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-48,ch=getchar();
     14     return x;
     15 }
     16 inline ll qpow(ll x,ll y){
     17     ll ans=1;
     18     while(y){
     19         if(y&1)ans=ans*x%mod;
     20         x=x*x%mod;
     21         y>>=1;
     22     }
     23     return ans;
     24 }
     25 inline void add(int x,int y){
     26     ne[++tot]=fi[x];
     27     fi[x]=tot;
     28     to[tot]=y;
     29 }
     30 ll dfs(int x,int fa){
     31     ff[x]=1;siz[x]=1;
     32     for(int i=fi[x];i;i=ne[i]){
     33         int y=to[i];
     34         if(y!=fa){
     35             ff[x]=ff[x]*dfs(y,x)%mod;
     36             siz[x]+=siz[y];
     37         }
     38     }
     39     ff[x]=ff[x]*js[fa?du[x]-1:du[x]]%mod;
     40     return ff[x];
     41 }
     42 void insert(int &x,int l,int r,int pos,int val){
     43     if(!x)x=++tt;
     44     if(l==r){
     45         sum[x]+=val;
     46         return;
     47     }
     48     int mid=(l+r)>>1;
     49     if(pos<=mid)insert(lc[x],l,mid,pos,val);
     50     else insert(rc[x],mid+1,r,pos,val);
     51     sum[x]=sum[lc[x]]+sum[rc[x]];
     52 }
     53 int query(int x,int l,int r,int pos){
     54     if(pos<=0)return 0;
     55     if(l==r)return sum[x];
     56     int mid=(l+r)>>1;
     57     if(pos<=mid)return query(lc[x],l,mid,pos);
     58     return query(rc[x],mid+1,r,pos)+sum[lc[x]];
     59 }
     60 bool check(int x,int l,int r,int pos){
     61     if(l==r)return sum[x];
     62     int mid=(l+r)>>1;
     63     if(pos<=mid)return check(lc[x],l,mid,pos);
     64     return check(rc[x],mid+1,r,pos);
     65 }
     66 bool dfs2(int x,int fa){
     67     int la=p+1,num=fa?du[x]-1:du[x];
     68     fc[x]=0;p++;
     69     ll t=0;
     70     sort(h[x].begin(),h[x].end());
     71     for(int i=fi[x];i;i=ne[i])
     72         if(to[i]!=fa)
     73             insert(r[x],1,n,to[i],1);
     74     while(p-la!=siz[x]-1){
     75         num--;int y=b[p+1];
     76         ff[x]=ff[x]*qpow(num+1,mod-2)%mod;
     77         fc[x]=(fc[x]+query(r[x],1,n,b[p+1]-1)*ff[x])%mod;
     78         if(!check(r[x],1,n,b[p+1])){
     79             p=siz[x]+la-1;
     80             return false;
     81         }
     82         insert(r[x],1,n,b[p+1],-1);
     83         ff[x]=ff[x]*qpow(ff[y],mod-2)%mod;
     84         if(!dfs2(b[p+1],x)){
     85             p=siz[x]-1+la;
     86             fc[x]=(fc[x]+fc[y]*ff[x])%mod;
     87             return false;
     88         }
     89         fc[x]=(fc[x]+fc[y]*ff[x])%mod;
     90     }
     91     return true;
     92 }
     93 int main(){
     94 //    freopen("t.in","r",stdin);
     95     n=read();js[0]=1;ni[0]=1;
     96     for(int i=1;i<=n;i++)
     97         b[i]=read();
     98     for(int i=1,x,y;i<n;i++){
     99         x=read(),y=read();
    100         add(x,y);add(y,x);
    101         du[x]++,du[y]++;
    102     }
    103     for(int i=1;i<=n;i++)
    104         js[i]=js[i-1]*i%mod,ni[i]=qpow(js[i],mod-2);
    105     f[1]=js[du[1]];
    106     for(int i=2;i<=n;i++)f[1]=f[1]*js[du[i]-1]%mod;
    107     for(int i=2;i<=b[1];i++)
    108         f[i]=f[1]*ni[du[i]-1]%mod*js[du[i]]%mod*ni[du[1]]%mod*js[du[1]-1]%mod;
    109     for(int i=1;i<=b[1];i++){
    110         if(i<b[1]){
    111             ans=(ans+f[i])%mod;
    112         }
    113         if(i==b[1]){
    114             p=0;
    115             dfs(i,0);
    116             dfs2(i,0);
    117             ans=(ans+fc[i])%mod;
    118         }
    119     }
    120     printf("%lld
    ",ans);
    121     return 0;
    122 }
    View Code

    模拟23

     T1.

      简单dp,没了.

    T2.

      这题做法非常的多,我可能是唯一一个二分AC的,细节很多,考试时少剪一个枝T成了60

      对于每一个点他的积水高度显然单调,我们可以二分这个高度,然后从这个点开始dfs,若成立,将与该点相连的所有高度小于ans的全部改成这个高度,注意不要重复遍历同一点,会将复杂度从n^2变成n^3

      二分挺恶心的,不重复遍历特判错了很容易wa,重复遍历就会T

      总复杂度nmlognm,复杂度还是正确的.

     1 #include<bits/stdc++.h>
     2 #define cri const register int
     3 using namespace std;
     4 const int zx[4]={1,-1,0,0},zy[4]={0,0,-1,1};
     5 int n,m,a[305][305],res[305][305],tim;
     6 int vv[305][305],tot;
     7 char v[305][305];
     8 bool dfs2(cri x,cri y,cri val){
     9     if(a[x][y]>=val)return true;
    10     vv[x][y]=tim;
    11     for(int i=0;i<=3;i++){
    12         int ax=x+zx[i],ay=y+zy[i];
    13         if(ax<0||ay<0||ax>n+1||ay>n+1)return false;
    14         if(v[ax][ay]&&a[ax][ay]+res[ax][ay]<val)return false;
    15         if(v[ax][ay]&&a[ax][ay]>=val)continue;
    16         if(vv[ax][ay]!=tim){
    17             if(!dfs2(ax,ay,val))return false;
    18         }
    19     }
    20     return true;
    21 }
    22 inline bool check(int x,int y,int val){
    23     tim++;
    24     return dfs2(x,y,val);
    25 }
    26 void dfs(cri x,cri y,cri val){
    27     res[x][y]=max(val-a[x][y],0);
    28     v[x][y]=true;
    29     if(a[x][y]>=val)return;
    30     for(int i=0;i<=3;i++){
    31         int ax=x+zx[i],ay=y+zy[i];
    32         if(v[ax][ay]||ax<=0||ay<=0||ax>n||ay>m)continue;
    33         dfs(ax,ay,val);
    34     }
    35 }
    36 struct keng{
    37     int x,y,a;
    38     friend bool operator < (keng a,keng b){
    39         return a.a<b.a;
    40     }
    41 }aa[100005];
    42 int main(){
    43     scanf("%d%d",&n,&m);
    44     for(int i=1;i<=n;i++)
    45         for(int j=1;j<=m;j++)
    46             scanf("%d",&aa[++tot].a),aa[tot].x=i,aa[tot].y=j,a[i][j]=aa[tot].a;
    47     sort(aa+1,aa+tot+1);
    48     for(int i=1;i<=tot;i++){
    49         if(!v[aa[i].x][aa[i].y]){
    50             int l=0,r=1e9,ans=-1e9;
    51             while(l<=r){
    52                 int mid=(l+r)>>1;
    53                 if(check(aa[i].x,aa[i].y,mid))ans=max(ans,mid),l=mid+1;
    54                 else r=mid-1;
    55             }
    56             dfs(aa[i].x,aa[i].y,ans);
    57         }
    58     }
    59     for(int i=1;i<=n;i++){
    60         for(int j=1;j<=m;j++)
    61             printf("%d ",res[i][j]);
    62         puts("");
    63     }
    64     return 0;
    65 }
    View Code

    T3,

      容斥好题

      我是看题解做的,主要解释一下f (i) = ∑ d μ(d)g(d)

      算了不想打公式了,自己反演去吧

  • 相关阅读:
    Android使用sqlliteOpenhelper更改数据库的存储路径放到SD卡上
    递归实现全排列(一)
    poj_1284_原根
    绝对让你理解Android中的Context
    Java Web---登录验证和字符编码过滤器
    ceph理论及部署配置实践
    ceph for openstack快速部署实施
    php set env
    基于本地iso 搭建的本地yum源 安装部署openldap
    ceph rpm foor rhel6
  • 原文地址:https://www.cnblogs.com/hzoi-cbx/p/11364534.html
Copyright © 2011-2022 走看看