NOIP模拟测试2-5

那年仲夏 提交于 2020-08-13 17:19:43

该补一下以前挖的坑了

先总结一下

第二次

T1 搜索+剪枝

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #define ll long long
  4 using namespace std;
  5 const int maxn=8005;
  6 int a[maxn],n,js[maxn];
  7 bool jk[maxn];
  8 ll ans;
  9 bool judge(int l,int r)
 10 {
 11     int i=l;
 12     while(i<r)
 13     {
 14         if(a[i]+1!=a[i+1])return 0;
 15         else i++;
 16     }
 17     return 1;
 18 }
 19 void out()
 20 {
 21     for(int i=1;i<=(1<<n);i++)
 22     {
 23         cout<<a[i]<<" ";
 24     }
 25     cout<<endl;
 26 }
 27 void search(int num,int last)
 28 {
 29    //out();//cout<<"->"<<endl;
 30     if(judge(1,1<<n)){ans+=js[num];return ;}
 31     if(last==n+1)return ;
 32     int must1=0,must2=0;
 33     for(int j=1;j<=(1<<n);j+=(1<<last))
 34         {
 35             if(!judge(j,j+(1<<last)-1)&&!must1)must1=j;
 36             else if(!judge(j,j+(1<<last)-1)&&must1&&!must2)must2=j;
 37             else if(!judge(j,j+(1<<last)-1))return ;
 38         }
 39     if(!must1&&!must2)search(num,last+1);
 40     else if(!must2)
 41     {
 42         int j=must1,k=must1+(1<<(last-1));
 43         int kx=0;
 44         while(kx<(1<<(last-1)))
 45         {
 46              swap(a[j+kx],a[k+kx]);
 47              kx++;
 48         }
 49         search(num+1,last+1);
 50         kx=0;
 51         while(kx<(1<<(last-1)))
 52         {
 53              swap(a[j+kx],a[k+kx]);
 54              kx++;
 55         }
 56         return ;
 57     }
 58     else
 59     {
 60         int jj[2]={},kk[2]={};
 61        // cout<<must1<<" "<<must2<<endl;
 62        jj[0]=must1,jj[1]=must1+(1<<(last-1));
 63        kk[0]=must2,kk[1]=must2+(1<<(last-1));
 64        //cout<<jj[1]<<" "<<kk[1]<<endl;
 65        for(int i=0;i<=1;i++)
 66            for(int j=0;j<=1;j++)
 67            {
 68                 //out();
 69                 //cout<<jj[i]<<" "<<kk[j]<<endl;
 70                 int kx=0;
 71                 while(kx<(1<<(last-1)))
 72                 {
 73                       swap(a[jj[i]+kx],a[kk[j]+kx]);
 74                       kx++;
 75                 }
 76                 search(num+1,last+1);
 77                 kx=0;
 78                 while(kx<(1<<(last-1)))
 79                 {
 80                       swap(a[jj[i]+kx],a[kk[j]+kx]);
 81                       kx++;
 82                 }
 83                 
 84            }
 85     }
 86     return ;
 87 }
 88 int main()
 89 {
 90     scanf("%d",&n);
 91     js[1]=1;
 92     for(int i=2;i<=n;i++)
 93         js[i]=js[i-1]*i;
 94     for(int i=1;i<=(1<<n);i++)
 95     {
 96         scanf("%d",&a[i]);
 97     }
 98         search(0,1);
 99         cout<<ans<<endl;
100         return 0;
101 }
View Code

 

 

 

T2 划艇 高难标记

31分算法:线段树优化DP 

AC算法:

区间离散化。

跨区间显然,同区间组合计数。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #define mod DeepinC
 5 #define maxn 505
 6 using namespace std;
 7 int l[maxn*2],len[maxn*2],sum[maxn*2][maxn*2],num[maxn*2][maxn*2],a[maxn],b[maxn],f[maxn][maxn*2],inv[maxn*10+5];
 8 const int mod=1e9+7;
 9 int qpower(int a,int b)
10 {
11     int ans=1;
12     while(b)
13     {
14         if(b&1)ans=1ll*ans*a%mod;
15         b>>=1;
16         a=1ll*a*a%mod;
17     }
18     return ans;
19 }
20 void get_inv()
21 {
22     for(int i=1;i<=500;i++)
23         inv[i]=qpower(i,mod-2);
24     return ;
25 }
26 int main()
27 {
28     get_inv();
29     int n,tot=0,ans=0;
30     scanf("%d",&n);
31     for(int i=1;i<=n;i++)
32     {
33         scanf("%d%d",&a[i],&b[i]);
34         b[i]++;
35         l[++tot]=a[i];
36         l[++tot]=b[i];
37     }
38     sort(l+1,l+tot+1);
39     tot=unique(l+1,l+tot+1)-l-1;
40     for(int i=1;i<tot;i++)
41     {
42         len[i]=l[i+1]-l[i];
43         //cout<<i<<" "<<len[i]<<endl;
44     }
45     for(int i=1;i<=n;i++)
46     {
47         a[i]=lower_bound(l+1,l+tot+1,a[i])-l;
48         b[i]=lower_bound(l+1,l+tot+1,b[i])-l-1;
49     }
50     sum[0][0]=1;
51     for(int i=1;i<=n;i++)
52     {
53         sum[i][0]=1;
54     }
55     for(int j=1;j<=tot;j++)sum[0][j]=1;
56     for(int i=1;i<=n;i++)
57     {
58         for(int j=a[i];j<=b[i];j++)
59         {
60             f[i][j]=1ll*sum[i-1][j-1]*len[j]%mod;
61            // cout<<f[i][j]<<endl;
62             int o=1,C=(len[j]-1)%mod;
63             for(int k=i-1;k;k--)
64             {
65                 if(a[k]>j||b[k]<j)continue;
66                 o++;
67                 C=1ll*C*(o+len[j]-2)%mod*inv[o]%mod;
68                 //cout<<C<<endl;
69                 f[i][j]=(f[i][j]+1ll*C*sum[k-1][j-1]%mod)%mod;
70             }
71             ///cout<<f[i][j]<<endl;
72             ans+=f[i][j];
73             ans%=mod;
74         }
75         for(int j=1;j<=tot;j++)
76             sum[i][j]=((1ll*sum[i-1][j]+sum[i][j-1])%mod-sum[i-1][j-1]+f[i][j]+mod)%mod;
77     }       
78     cout<<ans<<endl;
79     return 0;
80 }
View Code

 

 

 

T3 放棋子:DP

  设g[i][j][k]表示用k个棋子填满i行j列的方案,设f[i][j][k]表示用前k种棋子填满i行j列的方案

  容斥计算g数组: 

     

   那么f数组 :

    

   最终答案:

(图片来自https://www.cnblogs.com/yanshannan/p/9467292.html,特此鸣谢)

AC代码:

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define maxn 35
 5 using namespace std;
 6 const int mod=1e9+9;
 7 int C[maxn*maxn][maxn*maxn],g[maxn][maxn],f[maxn][maxn][maxn*maxn],cn[maxn];
 8 int moded(int x)
 9 {
10     if(x<0)return x+mod;
11     return x>=mod?x-mod:x;
12 }
13 int main()
14 {
15    // freopen("out.txt","w",stdout);
16     int n,m,c,tot=0;
17     scanf("%d%d%d",&n,&m,&c);
18     for(int i=1;i<=c;i++)
19     {
20         scanf("%d",&cn[i]);
21         tot=max(tot,cn[i]);
22     }
23     for(int i=1;i<=900;i++)
24     {
25         C[i][0]=C[i][i]=1;
26         for(int j=1;j<i;j++)
27             C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
28     }
29     f[0][0][0]=1;
30     int ans=0;
31     for(int k=1;k<=c;k++)
32     {
33         memset(g,0,sizeof(g));
34         for(int i=1;i<=n;i++)
35             for(int j=1;j<=m;j++)
36                 {
37                     g[i][j]=C[i*j][cn[k]];
38                     for(int ii=0;ii<=i;ii++)
39                         for(int jj=0;jj<=j;jj++)
40                         {
41                             if(ii==i&&jj==j)continue;
42                             g[i][j]=(g[i][j]-1ll*g[ii][jj]*C[i][ii]%mod*C[j][jj]%mod+mod)%mod;
43                         }
44                     //cout<<k<<" "<<i<<" "<<j<<" "<<" "<<g[i][j]<<endl;
45                 }
46         for(int i=1;i<=n;i++)
47             for(int j=1;j<=m;j++)
48             {
49                     for(int ii=0;ii<i;ii++)
50                         for(int jj=0;jj<j;jj++)
51                         {
52                             f[i][j][k]=(f[i][j][k]+1ll*f[ii][jj][k-1]*C[n-ii][i-ii]%mod*C[m-jj][j-jj]%mod*g[i-ii][j-jj]%mod)%mod;
53                             //if(k==c&&i==n&&j==m)cout<<ii<<" "<<jj<<" "<<f[ii][jj][k-1]<<endl;
54                         }
55                      if(k==c)
56                      {
57                         ans=moded(ans+f[i][j][c]);
58                         //if(i==n)cout<<i<<" "<<j<<" "<<f[i][j][c]<<endl;
59                      }
60            }
61         
62    }
63     cout<<ans<<endl;
64     return 0;
65 }
View Code

 

 

 

 

 

 

 

 

 

 

第三次

爆零。。。

T1:序列

乱搞,(鬼知道我打了一个什么倍增)

AC代码:(不会告诉你我是QJ的) 

感谢wd大佬的帮助%%DeepinC

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<cstring>
  5 #define maxn 200005
  6 #define maxq 1001
  7 #include<vector>
  8 #include<algorithm>
  9 #define LL long long
 10 #define ts puts("--------");
 11 using namespace std;
 12 LL n,a[maxn],ans,need1[maxn],A[maxn],maxx,b[maxn][21],num[maxn],fr[maxn][21],Num[105],nuM[105],toty;
 13 LL prime[maxq*10000+5],tot,frprime[maxq*10000+5];
 14 bool isnotprime[maxq*10000+5];
 15 LL gcd(LL a,LL b)
 16 {
 17     return b==0?a:gcd(b,a%b);
 18 }
 19 LL qpower(LL a,LL b)
 20 {
 21     LL ans=1;
 22     while(b)
 23     {
 24         if(b&1)ans=ans*a;
 25         a=a*a;
 26         b>>=1;
 27     }
 28     return ans;
 29 }
 30 void pre()
 31 {
 32     for(int i=2;i<=maxq*10000;i++)
 33     {
 34         if(!isnotprime[i])
 35         {
 36             prime[++toty]=i;
 37             frprime[i]=i;
 38         }
 39         for(int j=1;j<=toty;j++)
 40         {
 41             if(i*prime[j]>maxq*10000)break;
 42             isnotprime[i*prime[j]]=1;
 43             frprime[i*prime[j]]=prime[j];
 44             if(!i%prime[j])break;
 45         }
 46     }
 47 }
 48 LL GetUse(LL x)
 49 {
 50     LL mt=x;
 51     if(x%10==0){
 52         while(x%10==0)x/=10;
 53         return x==1?10ll:mt;
 54     }
 55     if(x%7==0){
 56         while(x%7==0)x/=7;
 57         return x==1?7ll:mt;
 58     }
 59     if(x%6==0){
 60         while(x%6==0)x/=6;
 61         return x==1?6ll:mt;
 62     }
 63     if(x%5==0){
 64         while(x%5==0)x/=5;
 65         return x==1?5ll:mt;
 66     }
 67     if(x%3==0){
 68         while(x%3==0)x/=3;
 69         return x==1?3:mt;
 70     }
 71     if(x%2==0){
 72         while(x%2==0)x/=2;
 73         return x==1?2:mt;
 74     }
 75     return mt;
 76 }
 77 bool query(LL st,LL len)
 78 {
 79     LL cnt=0;
 80     for(LL i=st;i<=st+len-1;i++)
 81     {
 82         num[++cnt]=a[i];
 83     }
 84     sort(num+1,num+cnt+1);
 85     for(LL i=2;i<=cnt;i++)if(num[i]==num[i-1]){return 0;}
 86     return 1;
 87 }
 88 LL Get(LL x,LL q)
 89 {
 90     if(q==1)return x;
 91     while(x%q==0)x/=q;
 92     return x;
 93 }
 94 bool judge(LL len)
 95 {
 96     LL Q=0,now,F;
 97     for(LL i=1;i<=n-len+1;i++)
 98     {
 99         now=0;Q=0;
100         for(LL t=17;t>=1;t--)
101         {
102             if((1<<t)+now<=len){
103                 if(b[i+now][t]==-1){break;}
104             //    cout<<i<<' '<<len<<' '<<t<<' '<<now<<" from "<<n-len+1<<endl;
105                 if(!Q){Q=b[i+now][t];F=fr[i+now][t];}
106                 else if(b[i+now][t]==-1||Q!=b[i+now][t]||fr[i+now][t]!=F){break;}
107                 now+=(1<<t);
108                 if(now==len){
109                     if(Q==1||query(i,len))return 1;
110                     else break;
111                 }
112                 if(now==len-1){
113                     if(Q==1&&a[i+len-1]==a[i+len-2])return 1;
114                     if(a[i+len-1]>a[i+len-2]&&query(i,len)&&a[i+len-1]%a[i+len-2]==0)
115                     {
116                         LL t=a[i+len-1]/a[i+len-2];
117                         if(GetUse(t)==Q)return 1;
118                     }
119                     else 
120                     if(a[i+len-1]<a[i+len-2]&&query(i,len)&&a[i+len-2]%a[i+len-1]==0)
121                     {
122                         LL t=a[i+len-2]/a[i+len-1];
123                         if(GetUse(t)==Q)return 1;
124                     }
125                     break;
126                 }
127             }
128         }
129     }
130     return 0;
131 }
132 int main()
133 {
134     scanf("%lld",&n);
135     for(LL i=1;i<=n;i++)scanf("%lld",&a[i]);
136     for(LL i=2;i<=n;i++)
137         if(a[i]%a[i-1]==0){
138             b[i-1][1]=a[i]/a[i-1];
139             b[i-1][1]=GetUse(b[i-1][1]);
140             fr[i-1][1]=Get(a[i-1],b[i-1][1]);
141         }
142         else if(a[i-1]%a[i]==0){
143             b[i-1][1]=a[i-1]/a[i];
144             b[i-1][1]=GetUse(b[i-1][1]);
145             fr[i-1][1]=Get(a[i],b[i-1][1]);
146         }
147         else b[i-1][1]=-1;
148     b[n][1]=-1;
149     for(LL i=2;i<=17;i++)
150         for(LL j=1;j<=n;j++){
151             if(b[j][i-1]==b[j+(1<<(i-1))][i-1]&&b[j][i-1]!=-1&&fr[j][i-1]==fr[j+(1<<(i-1))][i-1])
152                 b[j][i]=b[j][i-1],fr[j][i]=fr[j][i-1];
153             else b[j][i]=-1;
154         }
155     LL l=2,r=n;
156     while(l<=r)
157     {
158         int mid=l+r>>1;
159         if(judge(mid)){ans=mid;l=mid+1;}
160         else r=mid-1;
161     }
162     cout<<ans<<endl;
163     return 0;
164 }
View Code

 

 

 

T2:熟练剖分   

概率期望不是DP

值得一提的是,wq学长为我们证明了某种树DP复杂度(枚举深度,子树大小。。):设(x,y)表示树上的一对节点对,那么考虑每个节点的贡献,每个节点会被它的父链上的每个节点计算一次,所以每个节点被计算n次即总复杂度n×n。

还有很重要的是,打成相加形式才是n^2,不然是n^3

n^2

复制代码
1 for(int j=size[x];j>=0;j--) 2  { 3 for(int k=0;k<=min(j,size[y]);k++) 4  { 5 f[x][j][1]=min(f[x][j][1],f[x][j-k][1]+f[y][k][1]); 6 f[x][j][0]=min(f[x][j][0],f[x][j-k][0]+min(f[y][k][0],f[y][k][1])); 7  } 8 }
复制代码

 

n^3

复制代码
1 for(int j=size[x];j>=0;j--) 2  { 3 for(int k=size[y];k>=0;k--) 4  { 5 f[x][j+k][1]=min(f[x][j+k][1],f[x][j][1]+f[y][k][1]); 6 f[x][j+k][0]=min(f[x][j+k][0],f[x][j][0]+min(f[y][k][0],f[y][k][1])); 7  } 8 }
复制代码

 

这道题就是这一类

AC代码:

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 using namespace std;
 6 const int mod=1e9+7;
 7 int n,indu[3100],root;
 8 vector<int>son[3100];
 9 long long f[3100][3100],g[2][2][3100],dep[3100];
10 long long pow(long long a,long long b){
11     long long ans=1;
12     a%=mod;
13     while(b){
14         if(b&1) ans=(ans*a)%mod;
15         b>>=1;
16         a=(a*a)%mod;
17     }
18     return ans%mod;
19 }
20 long long max(long long a,long long b){
21     return a>b?a:b;
22 }
23 void dfs(int x){
24     if(son[x].size()==0){
25         f[x][0]=1;
26         //printf("x=%d 代价=%d 方案数=%d\n",x,0,f[x][0]);
27         return;
28     }
29     for(int i=0;i<son[x].size();i++){
30         dfs(son[x][i]);
31         dep[x]=max(dep[x],dep[son[x][i]]+1);
32     }
33     memset(g,0,sizeof(g));
34     for(int i=1;i<=dep[son[x][0]]+1;i++){
35         g[0][0][i]=f[son[x][0]][i-1];
36         g[0][1][i]=f[son[x][0]][i];
37         //printf("g[%d][%d][%d]=%d g[%d][%d][%d]=%d\n",0,0,i,g[0][0][i],0,1,i,g[0][1][i]);
38     }
39     g[0][1][0]=f[son[x][0]][0];
40     int cur=0,upw=dep[son[x][0]]+1;
41     for(int i=1;i<son[x].size();i++){
42         memset(g[cur^1],0,sizeof(g[cur^1]));
43         for(int j=0;j<=upw;j++){
44             for(int k=0;k<=dep[son[x][i]];k++){
45                 (g[cur^1][0][max(j,k+1)]+=g[cur][0][j]*f[son[x][i]][k]%mod)%=mod;
46                 (g[cur^1][1][max(j,k+1)]+=g[cur][1][j]*f[son[x][i]][k]%mod)%=mod;
47                 (g[cur^1][1][max(j,k)]+=g[cur][0][j]*f[son[x][i]][k]%mod)%=mod;
48             }
49         }
50         upw=max(dep[son[x][i]]+1,upw);
51         cur^=1;
52     }
53     memcpy(f[x],g[cur][1],sizeof(f[x]));
54     //for(int i=0;i<=dep[x];i++) printf("x=%d 代价=%d 方案=%d\n",x,i,f[x][i]);
55 
56 }
57 int main(){
58     scanf("%d",&n);
59     int x,y;
60     long long num=1;
61     for(int i=1;i<=n;i++){
62         scanf("%d",&x);
63         for(int j=1;j<=x;j++){
64             scanf("%d",&y);
65             son[i].push_back(y);
66             indu[y]++;
67         }
68         if(x) (num*=pow(x,mod-2)%mod)%=mod;
69     }
70     for(int i=1;i<=n;i++){
71         if(indu[i]==0){
72             root=i;
73             break;
74         }
75     }
76     dfs(root);
77     long long sum=0;
78     for(int i=1;i<=n;i++) sum=(sum+i*f[root][i]%mod)%mod;
79     //cout<<sum<<" "<<num<<endl; 
80     printf("%lld\n",(sum%mod*num%mod)%mod);
81 }
View Code

 

 

T3:建造游乐场     高难标记

毒瘤题,码量极短,思维量极高23333333

为了保证考试总结的完整性 我决定借用外力(粘贴题解)

   

先不粘AC代码了(心虚)

 

 

 

第四次

T1 礼物:

实际上是个及其简单的概率期望

But....我经过一下午的钻研(死皮赖脸缠着学长)(以致学长无法吃鸡)才大致明白了

  f[i]=∑f[s]*p[j]+∑p[j]*f[i]+1  因为设f[i]表示买到状态为i到最终状态的期望次数  那么那么f[i]是可以由他的下一个状态转移过来  即所有的f[s].如果按原有的逻辑顺序对于f[i]来说转移到f[s]的概率是显然的  但是因为是倒着推,很显然f[s]就应该累加到f[i]上

所以:

正向求概率,反向求期望!

 1 #include<cstdio>
 2 #include<iostream>
 3 #define MAXN 25
 4 using namespace std;
 5 double p[MAXN],f[1<<22],wp[MAXN];
 6 int w[MAXN];
 7 int main()
 8 {
 9     int n;long long ans1=0;
10     scanf("%d",&n);
11     int maxk=(1<<n)-1;
12     for(int i=1;i<=n;i++)
13     {
14         scanf("%lf%d",&p[i],&w[i]);
15         ans1+=w[i];
16     }
17     cout<<ans1<<endl;
18     f[maxk]=0;
19     for(int i=0;i<=maxk;i++)
20     {
21         int state=i;
22         for(int j=1;j<=n;j++)
23         {
24             if((state&(1<<(j-1))))continue;
25             wp[state]+=p[j];
26         }
27     }
28     for(int i=maxk-1;i>=0;i--)
29     {
30         f[i]=1;
31         for(int j=1;j<=n;j++)
32         {
33             if((i&(1<<(j-1))))continue;
34             f[i]+=(f[i|(1<<(j-1))]*p[j]);
35         }
36         f[i]/=wp[i];
37         //cout<<i<<' '<<f[i]<<endl;
38     }
39     printf("%.3lf",f[0]);
40     return 0;
41 }
View Code

 

 

T2:通讯

Tarjan缩点+贪心板子题

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<queue>
  4 #include<cstring>
  5 #define LL long long
  6 #define mem(a) memset(a,0,sizeof(a))
  7 #define MAXN 200005
  8 #define LL long long
  9 using namespace std;
 10 struct node{
 11     LL to[MAXN],head[MAXN],w[MAXN],nxt[MAXN],d[MAXN],low[MAXN],dfn[MAXN],s[MAXN],top,tot,num,out[MAXN],n,m,c[MAXN];
 12     LL To[MAXN],Head[MAXN],W[MAXN],Nxt[MAXN],cnt,Cnt,ans;
 13     bool in_s[MAXN];
 14     void clear()
 15     {
 16         mem(head);mem(Head);cnt=Cnt=ans=tot=top=num=0;mem(in_s);mem(dfn);
 17     }
 18     void add(LL u,LL v,LL val)
 19     {
 20         to[++cnt]=v;
 21         nxt[cnt]=head[u];
 22         w[cnt]=val;
 23         head[u]=cnt;
 24         return ;
 25     }
 26     void Add(LL u,LL v,LL val)
 27     {
 28         To[++Cnt]=v;
 29         Nxt[Cnt]=Head[u];
 30         W[Cnt]=val;
 31         Head[u]=Cnt;
 32         return ;
 33     }
 34     void Tarjan(LL x)
 35     {
 36         dfn[x]=low[x]=++tot;
 37         s[++top]=x;
 38         in_s[x]=1;
 39         for(LL i=head[x];i;i=nxt[i])
 40         {
 41             LL y=to[i];
 42             if(!dfn[y])
 43             {
 44                 Tarjan(y);
 45                 low[x]=min(low[x],low[y]);
 46             }
 47             else if(in_s[y])
 48             {
 49                 low[x]=min(low[x],dfn[y]);
 50             }
 51         }
 52         if(low[x]==dfn[x])
 53         {
 54             num++;
 55             while(top)
 56             {
 57                 LL p=s[top--];
 58                 in_s[p]=0;
 59                 c[p]=num;
 60                 if(p==x)break;
 61             }
 62         }
 63     }
 64     void toposort()
 65     {
 66         queue<int>Q;
 67         memset(d,0x3f,sizeof(d));
 68         d[c[1]]=0;
 69         Q.push(c[1]);
 70         while(!Q.empty())
 71         {
 72             LL x=Q.front();Q.pop();
 73             for(LL i=Head[x];i;i=Nxt[i])
 74             {
 75                 LL y=To[i];
 76                 out[y]--;
 77                 if(W[i]<d[y])
 78                 {
 79                     d[y]=W[i];
 80                 }
 81                 if(!out[y])Q.push(y);
 82             }
 83         }
 84         return ;
 85     }
 86     void Build_new()
 87     {
 88         for(LL i=1;i<=n;i++)
 89             for(LL j=head[i];j;j=nxt[j])
 90             {
 91                 LL k=to[j];
 92                 if(c[i]!=c[k])
 93                 {
 94                     Add(c[i],c[k],w[j]);
 95                     out[c[k]]++;
 96                 }
 97             }
 98     }
 99     inline LL Rd()
100     {
101         register LL x=0;char c=getchar();
102         while(c>'9'||c<'0')c=getchar();
103         while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
104         return x;
105     }
106     void work()
107     {
108         while(1)
109         {
110             n=Rd(),m=Rd();
111             if(n==0&&m==0)return ;
112             clear();
113             while(m--)
114             {
115                 LL a=Rd(),b=Rd(),c=Rd();
116                 a++;b++;
117                 add(a,b,c);
118             }
119             Tarjan(1);
120             Build_new();
121             toposort();
122             for(LL i=1;i<=num;i++)ans+=d[i];
123             cout<<ans<<endl;
124         }
125     }
126 }E;
127 int main()
128 {
129     E.work();
130     return 0;
131 }
View Code

 

 

T3:奇袭(我不会玩甘宁啊)     高难标记

27分算法:维护前缀和扫描

74分算法:维护最大最小值

AC算法:分治

这里写的详细!!!

再次膜拜DeepinC

AC代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define MAXN 50005
 5 using namespace std;
 6 int ans;
 7 int w[MAXN],mi[MAXN],ma[MAXN],t[MAXN*2],n;
 8 inline int Rd()
 9 {
10     int x=0;char c=getchar();
11     while(c<'0'||c>'9')c=getchar();
12     while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
13     return x;
14 }
15 int solve(int l,int r)
16 {
17     if(l==r)return 1;
18     int mid=l+r>>1;
19     int lans=solve(l,mid),rans=solve(mid+1,r);
20     ans=lans+rans;
21     ma[mid]=mi[mid]=w[mid];
22     ma[mid+1]=mi[mid+1]=w[mid+1];
23     for(int i=mid-1;i>=l;i--)
24     {
25         ma[i]=max(w[i],ma[i+1]);
26         mi[i]=min(w[i],mi[i+1]);
27     }
28     for(int i=mid+2;i<=r;i++)
29     {
30         ma[i]=max(ma[i-1],w[i]);
31         mi[i]=min(mi[i-1],w[i]);
32     }
33     for(int i=mid;i>=l;i--)
34     {
35         int j=ma[i]-mi[i]+i;
36         if(j>mid&&j<=r&&ma[j]<=ma[i]&&mi[j]>=mi[i])ans++;
37     }
38     for(int i=mid+1;i<=r;i++)
39     {
40         int j=i-ma[i]+mi[i];
41         if(j<=mid&&j>=l&&ma[j]<=ma[i]&&mi[j]>=mi[i])ans++;
42     }
43     int head,tail;
44     head=tail=mid+1;
45     for(int i=mid;i>=l;i--)// maxn in left && minn in right    mi[j]<mi[i] && ma[j] <ma[i] 
46     {
47         while(ma[tail]<=ma[i]&&tail<=r){t[tail+mi[tail]]++;tail++;}
48         while(mi[head]>=mi[i]&&head<=r){t[head+mi[head]]--;head++;}
49         if(t[i+ma[i]]>0)ans+=t[i+ma[i]];
50     }
51     while(head<tail){t[head+mi[head]]--;head++;}    
52     while(tail<head){t[tail+mi[tail]]++;tail++;}
53     head=tail=mid;
54     for(int i=mid+1;i<=r;i++)
55     {
56         while(ma[tail]<=ma[i]&&tail>=l){t[tail-mi[tail]+MAXN]++;tail--;}
57         while(mi[head]>=mi[i]&&head>=l){t[head-mi[head]+MAXN]--;head--;}
58         if(t[MAXN+i-ma[i]]>0)ans+=t[MAXN+i-ma[i]];
59     }
60     while(head>tail){t[head-mi[head]+MAXN]--;head--;}    
61     while(tail>head){t[tail-mi[tail]+MAXN]++;tail--;}
62     return ans;
63 }
64 int main()
65 {
66  //     freopen("da.in","r",stdin);
67 //    freopen("my.out","w",stdout);
68     n=Rd();
69     for(int i=1;i<=n;i++)
70     {
71         int a=Rd(),b=Rd();
72         w[a]=b;
73     }
74     printf("%d\n",solve(1,n));
75     return 0;
76 }
77 /*
78 8
79 1 2
80 2 6
81 3 1
82 4 7
83 5 3
84 6 5
85 7 4
86 8 8
87 */
View Code

 

 

 

 

第五次

T1:星际旅行

考试想到正解,没有判连通

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 const long long MAXN=200005;
 7 long long n,m,out[MAXN],s[MAXN],t[MAXN],add,addy;
 8 long long C[MAXN][3];
 9 long long ans;
10 int f[MAXN],siz[MAXN];
11 bool vst[MAXN];
12 inline long long Rd()
13 {
14     register long long x=0;
15     char c=getchar();
16     while(c>'9'||c<'0')c=getchar();
17     while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
18     return x;
19 }
20 int Get(int a)
21 {
22     return f[a]==a?a:f[a]=Get(f[a]);
23 }
24 void un_ion(int a,int b)
25 {
26     int fa=Get(a),fb=Get(b);
27     f[fa]=fb;
28     siz[fb]+=siz[fa];
29 }
30 int main()
31 {
32 //    freopen("out.in","r",stdin);
33 //    freopen("a.txt","w",stdout);
34     n=Rd();m=Rd();
35     for(int i=1;i<=n;i++)f[i]=i,siz[i]=1;
36     for(long long i=1;i<=m;i++)
37     {
38         s[i]=Rd();t[i]=Rd();
39         vst[s[i]]=vst[t[i]]=1;
40         if(Get(s[i])!=Get(t[i]))un_ion(s[i],t[i]);
41         if(s[i]==t[i]){add++;ans+=m-add;}
42         else {out[s[i]]++;out[t[i]]++;addy++;}
43     }
44     int xup=0;
45     for(int i=1;i<=n;i++)if(!vst[i])xup++;
46     for(int i=1;i<=n;i++)
47         if(vst[i]&&siz[Get(i)]!=n-xup){cout<<0<<endl;return 0;}
48         else if(vst[i]) break;
49     C[1][0]=C[1][1]=1;
50     for(long long i=2;i<=m;i++)
51     {
52         C[i][0]=1;
53         for(long long j=1;j<=2;j++)
54             C[i][j]=C[i-1][j-1]+C[i-1][j];
55     }
56     for(long long i=1;i<=n;i++)
57         ans+=C[out[i]][2];
58     cout<<ans<<endl;
59     return 0;
60 }
View Code

 

T2:砍树

数论分块。

显然:

 

 

辣么移项后易得:(本博猪没有图,自行脑补)。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 int n;
 8 long long m,a[110],maxn;
 9 vector<long long>ok;
10 int judge(long long x){
11     long long len=0;
12     for(int i=1;i<=n;i++){
13         int g=ceil((double)a[i]/(double)x);
14         len+=(long long)g;
15     }
16     //cout<<x<<" "<<len<<endl;
17     if(x<=m/len) return 1;
18     return 0;
19 }
20 int main(){
21     scanf("%d%lld",&n,&m);
22     for(int i=1;i<=n;i++) scanf("%lld",&a[i]),m+=a[i],maxn=max(a[i],maxn);
23 //    cout<<"fsdf"<<endl;
24     //maxn=1000000;
25     for(long long i=1;i<=m;i++){
26         long long sg=0;
27         for(int j=1;j<=n;j++){
28             sg+=ceil((double)a[j]/(double)i);
29         }
30         //cout<<i<<" "<<sg<<endl;
31         long long sb=m/sg;
32         //cout<<sb<<endl;
33         ok.push_back(sb);
34         i=m/(m/i);
35     }
36     long long ans=0;
37     sort(ok.begin(),ok.end());
38     for(int i=ok.size()-1;i>=0;i--){
39     //    cout<<ok[i]<<endl;
40         if(judge(ok[i])){
41             ans=ok[i];
42             break;
43         }
44     }
45     printf("%lld\n",ans);
46 }
View Code

 

 

T3:超级树

再次借用wd大佬题解

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #define LL long long
 4 #define MAXN 305
 5 using namespace std;
 6 LL dp[MAXN][MAXN],siz[MAXN];
 7 int main()
 8 {
 9     LL k,mod;
10     scanf("%lld%lld",&k,&mod);
11     dp[1][1]=dp[1][0]=1;
12     siz[1]=1;
13     for(int i=2;i<=k;i++)
14     {
15         if(siz[i-1]<k)siz[i]=siz[i-1]+siz[i-1]+1;
16         else siz[i]=k+1;
17         for(int l=0;l<=min(k,siz[i-1]);l++)
18             for(int r=0;r<=min(k,siz[i-1]);r++)
19             {
20                 if(l+r>k)break;
21                 LL num=dp[i-1][l]*dp[i-1][r]%mod;
22                 if(!num)continue;
23                 dp[i][l+r]+=num;if(dp[i][l+r]>=mod)dp[i][l+r]-=mod;
24                 dp[i][l+r+1]+=num;if(dp[i][l+r+1]>=mod)dp[i][l+r+1]-=mod;
25                 (dp[i][l+r]+=num*(l+r)*2)%=mod;
26                 if(l+r>0)
27                 (dp[i][l+r-1]+=num*l*r*2)%=mod;
28                 if(l+r>0)
29                 (dp[i][l+r-1]+=num*(l*(l-1)+r*(r-1)))%=mod;
30             }
31     }
32     cout<<dp[k][1]%mod<<endl;
33     return 0;
34 }
View Code

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!