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\n",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)

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章