zoukankan      html  css  js  c++  java
  • 17-09-13模拟赛

    T1:可以发现,满足题设条件的方案只有三个位置成一行或是三个位置成直角。

    记录每一行与列白色方格的个数,由此求得红色方格的个数。

    对于成行或成列的情况,分别求出中间是红色或白色的情况的方案个数。

    对于成直角的情况,则枚举直角顶点,计算其对应行与对应列的方案个数。

    注意答案可能会超过long long范围。

    Code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define ll long long
     5 #define mod 1000000000000000000
     6 #define MN 4000005
     7 #define row(x) (sum[x])
     8 #define col(x) (sum[x+n])
     9 using namespace std;
    10 inline int in(){
    11     int x=0;bool f=0; char c;
    12     for (;(c=getchar())<'0'||c>'9';f=c=='-');
    13     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
    14     return f?-x:x;
    15 }
    16 struct exll{
    17     ll a[2];
    18 }ans;
    19 ll sum[MN];
    20 inline exll operator +(const exll &x,const ll &y){
    21     exll z;memset(z.a,0,sizeof(z.a));
    22     z.a[1]=x.a[1]+y;z.a[0]=x.a[0]+(z.a[1]/mod);z.a[1]%=mod;return z;
    23 }
    24 char s[MN];
    25 int n,m;
    26 int main()
    27 {
    28     n=in();m=in();memset(ans.a,0,sizeof(ans.a));
    29     for (int i=0;i<n;++i){
    30         scanf("%s",s+i*m);for (int j=0;j<m;++j) 
    31         row(i)+=1ll*(s[i*m+j]-'0'),col(j)+=1ll*(s[i*m+j]-'0');
    32     }for (int i=0;i<n;++i)ans=ans+1ll*(row(i)*(m-row(i))*(m-row(i)-1)),ans=ans+1ll*(row(i)*(row(i)-1)*(m-row(i)));
    33     for (int i=0;i<m;++i) ans=ans+1ll*(col(i)*(n-col(i))*(n-col(i)-1)),ans=ans+1ll*(col(i)*(col(i)-1)*(n-col(i)));
    34     for (int i=0;i<n;++i)
    35     for (int j=0;j<m;++j){
    36         if (s[i*m+j]=='1') ans=ans+2ll*((m-row(i))*(n-col(j)));
    37         else ans=ans+2ll*(row(i)*col(j));
    38     }if (ans.a[0]) printf("%lld%018lld",ans.a[0],ans.a[1]);
    39     else printf("%lld",ans.a[1]);return 0;
    40 }

    T2:可以发现,对对一个数取φ会使该数的值以极快的速率下降。

    对一个大于1的奇数取φ,结果一定是偶数;对一个偶数取φ,结果一定小等于该数的一半;φ(1)=1.

    所以一个数最多取log级别次φ就能变为1.

    考虑用欧拉筛O(值域)求φ,而后用线段树维护序列的区间最大值和区间乘积。

    每次修改定位到一个区间后,如果该区间内最大值超过1,则继续往下递归,否则不用直接返回上一级;

    或者直到递归到长度为1的区间后,直接将该值取φ即可。修改的复杂度最多为O(n log n).

    Code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define ll long long
     5 #define L (x<<1)
     6 #define R (x<<1|1)
     7 #define mid ((l+r)>>1)
     8 #define mod 1000000007
     9 #define MN 200005
    10 #define MV 10000005
    11 using namespace std;
    12 inline int in(){
    13     int x=0;bool f=0; char c;
    14     for (;(c=getchar())<'0'||c>'9';f=c=='-');
    15     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
    16     return f?-x:x;
    17 }
    18 int mx[MN<<2],a[MN],phi[MV],pri[MV];
    19 int n,m,tp,x,y,mn=0,cnt=0;
    20 ll pro[MN<<2];
    21 inline void getphi(int n){
    22     phi[1]=1;for (int i=2;i<n;++i){
    23         if (!phi[i]) pri[++cnt]=i,phi[i]=i-1;
    24         for (int j=1;i*pri[j]<n&&j<=cnt;++j){
    25             if (i%pri[j]) phi[i*pri[j]]=phi[i]*phi[pri[j]];
    26             else {phi[i*pri[j]]=phi[i]*pri[j];break;}
    27         }
    28     }
    29 }
    30 inline void pushup(int x){
    31     mx[x]=max(mx[L],mx[R]);pro[x]=1ll*pro[L]*pro[R]%mod;
    32 }
    33 inline void pushdown(int x,int l,int r){
    34     if (mx[x]==1) return;
    35     if (l==r) {mx[x]=pro[x]=phi[mx[x]];return;}
    36     pushdown(L,l,mid);pushdown(R,mid+1,r);pushup(x);
    37 }
    38 inline void update(int x,int l,int r,int a,int b){
    39     if (a<=l&&b>=r) {pushdown(x,l,r);return;}
    40     if (a<=mid) update(L,l,mid,a,b);
    41     if (b>mid) update(R,mid+1,r,a,b);pushup(x);
    42 }
    43 inline ll query(int x,int l,int r,int a,int b){
    44     if (a<=l&&b>=r) return pro[x];
    45     if (b<=mid) return query(L,l,mid,a,b);
    46     else if (a>mid) return query(R,mid+1,r,a,b);
    47     else return 1ll*query(L,l,mid,a,mid)*query(R,mid+1,r,mid+1,b)%mod;
    48 }
    49 inline void build(int x,int l,int r){
    50     if (l==r){mx[x]=pro[x]=a[l];return;}
    51     build(L,l,mid);build(R,mid+1,r);pushup(x);
    52 }
    53 int main()
    54 {
    55     n=in();m=in();for (int i=1;i<=n;++i)
    56     a[i]=in(),mn=max(mn,a[i]);getphi(mn+1);build(1,1,n);
    57     for (int i=1;i<=m;++i){
    58         tp=in();x=in();y=in();
    59         if (tp==1) update(1,1,n,x,y);
    60         else printf("%lld
    ",query(1,1,n,x,y));
    61     }return 0;
    62 }

    T3:最大权闭合子图,即二分图匹配。

    观察到质数除了2以外都是奇数,所以起冲突的两个数奇偶性必定不同,所以将奇数分为一边,偶数分为一边。

    又因为构成2两数之和的只有1+1,又因为乘以1对答案没有影响,所以读入时可以舍弃1的情况。

    建图时对每个数取对数,变为求和最大。

    S向每个奇数连边权为log(权值)的边,每个偶数向T连边权为log(权值)的边,有冲突的点之间连边,边权为inf.

    得出答案时,从S开始dfs,每次只走满流的边。

    对于左边的点,如果能遍历到,那么把它加入答案;对于右边的点,如果不能遍历到,把它加入答案。

    Code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<queue>
     6 #define ll long long
     7 #define ld long double
     8 #define MN 1000005
     9 #define MM 5005
    10 #define mod 1000000007
    11 #define inf 0x7fffffff
    12 #define eps 1e-12
    13 using namespace std;
    14 inline int in(){
    15     int x=0;bool f=0; char c;
    16     for (;(c=getchar())<'0'||c>'9';f=c=='-');
    17     for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0');
    18     return f?-x:x;
    19 }
    20 struct edge{
    21     int to,next;
    22     ld cap;
    23 }e[MN<<1];
    24 int head[MM],iter[MM],lev[MM],b[2][MM];
    25 int cnt=1,s,t,n,x;
    26 bool vis[MM],np[MN];
    27 inline void ins(int x,int y,ld cp){
    28     e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt;e[cnt].cap=cp;
    29     e[++cnt].to=x;e[cnt].next=head[y];head[y]=cnt;e[cnt].cap=0;
    30 }
    31 inline void getp(int n){
    32     np[1]=1;for (int i=2;i*i<n;++i)
    33     if (!np[i]) for (int j=i;i*j<n;++j)np[i*j]=1;
    34 }
    35 inline void bfs(){
    36     queue<int>q;memset(lev,-1,sizeof(lev));
    37     lev[s]=0;q.push(s);
    38     while (!q.empty()){
    39         int u=q.front();q.pop();
    40         for (int i=head[u];i;i=e[i].next){
    41             int v=e[i].to;
    42             if (e[i].cap>eps&&lev[v]==-1)
    43             lev[v]=lev[u]+1,q.push(v);
    44         }
    45     } 
    46 }
    47 inline ld dfs(int u,ld f){
    48     if (u==t) return f;ld used=0.0;
    49     for (int &i=iter[u];i;i=e[i].next){
    50         int v=e[i].to;
    51         if (e[i].cap>eps&&lev[u]+eps<lev[v]){
    52             ld w=dfs(v,min(f-used,e[i].cap));
    53             if (w>eps){
    54                 e[i].cap-=w;e[i^1].cap+=w;used+=w;
    55                 if (used==f) return f;
    56             }
    57         } 
    58     }return used;
    59 }
    60 inline void dinic(){
    61     while (1){
    62         bfs();if (lev[t]==-1) return;
    63         memcpy(iter,head,sizeof(head));
    64         ld d=0.0;while ((d=dfs(s,inf))>eps);
    65     }
    66 }
    67 inline void dfs2(int u){
    68     for (int i=head[u];i;i=e[i].next){
    69         int v=e[i].to;
    70         if (e[i].cap>eps&&!vis[v]) vis[v]=1,dfs2(v);
    71     }
    72 }
    73 int main()
    74 {
    75     n=in();getp(MN+1);s=0;t=n+1;
    76     for (int i=1;i<=n;++i){x=in();if (x==1) continue;b[x&1][++b[x&1][0]]=x;}
    77     for (int i=1;i<=b[0][0];++i) ins(s,i,log2(b[0][i]));
    78     for (int i=1;i<=b[1][0];++i) ins(i+b[0][0],t,log2(b[1][i]));
    79     for (int i=1;i<=b[0][0];++i)
    80     for (int j=1;j<=b[1][0];++j)
    81     if (!np[b[0][i]+b[1][j]]) ins(i,j+b[0][0],inf);
    82     dinic();vis[s]=1;dfs2(s);ll ans=1ll;
    83     for (int i=1;i<=b[0][0];++i) if (vis[i]) ans=1ll*ans*b[0][i]%mod;
    84     for (int i=1;i<=b[1][0];++i) if (!vis[i+b[0][0]]) ans=1ll*ans*b[1][i]%mod;
    85     printf("%lld",ans);return 0;
    86 }
  • 相关阅读:
    去掉移动端页面 input, textarea, button, a 标签获取焦点时显示的黑影
    屏蔽敏感词的正则表达式
    flex弹性布局详解
    解决微信小程序手机请求数据不返回的问题
    基于Express框架开发接口
    window平台下MongoDB安装和环境搭建
    搭建基于Express框架运行环境
    详解闭包(推荐)
    解决浏览器兼容ES6特性
    ES6之promise的使用
  • 原文地址:https://www.cnblogs.com/codingutopia/p/test170913.html
Copyright © 2011-2022 走看看