zoukankan      html  css  js  c++  java
  • [考试反思]1002csp-s模拟测试57:平庸

    一天两场,感觉要完。

    不粘排行榜,太壮观了。

    #1:190

    #2:180

    #4:160

    #35:150

    #37:140

    #39:120

    #kx:20呃。。。

    最后一个是考试结束后了。

    又是CE盖40分。其实离#2不远。。。

    调试语句没删干净,开O2编译出一条编译错误,没看,以为是那条关于scanf的warning。

    然而并不是。

    一定要仔细检查编译信息!!!交代码前一定要编译!!!

    还有其实T1险些出锅,看错了题。

    考试结束前7分钟重新看了一遍发现不对劲,+100pts。

    看题!!!

    要检查!!!

    T1:天空龙

    不会讲。写的超麻烦。

     1 #include<cstdio>
     2 main(){
     3     int t;scanf("%d",&t);
     4     while(t--){
     5         int a,b,c,x,y,z;scanf("%d%d%d%d%d%d",&a,&b,&c,&x,&y,&z);
     6         int det=(x>a)+(y>b)+(z>c);
     7         if(det==0){puts("YES");continue;}
     8         if(det==3){puts("NO");continue;}
     9         if(det==2){
    10             if(a>=x)puts(a-x>>1>=y-b+z-c?"YES":"NO");
    11             if(b>=y)puts(b-y>>1>=x-a+z-c?"YES":"NO");
    12             if(c>=z)puts(c-z>>1>=x-a+y-b?"YES":"NO");
    13         }
    14         if(det==1){
    15             if(x>a)puts(x-a<=(b-y>>1)+(c-z>>1)?"YES":"NO");
    16             if(y>b)puts(y-b<=(a-x>>1)+(c-z>>1)?"YES":"NO");
    17             if(z>c)puts(z-c<=(a-x>>1)+(b-y>>1)?"YES":"NO");
    18         }
    19     }
    20 }
    View Code

    T2:巨神兵

    数据范围显然状压n,但是状压表示什么?

    因为要造DAG,所以一定有拓扑序,就存哪些点已经被拓扑了就行。

    但是有的DAG的拓扑序不唯一。要容斥掉。(容斥系数我会证了感谢吧人擦)

    枚举补集的子集,枚举子集的高效方法一直不会,上网颓了一个。

    for(int st=S;st;(--st)&=S);这样st就会遍历S的所有子集。

    这题也严重卡常,不能通过直接枚举n来判断二进制下是否存在这个点,而是要lowbit来直接取出一位。

     1 #include<cstdio>
     2 #define mod 1000000007
     3 int fir[18],l[299],to[299],cnt,n,m,cr[18],sz[1666666],pre[18],re[1666666];
     4 long long pw[111],dp[1666666];
     5 void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
     6 main(){//freopen("obelisk8.in","r",stdin);
     7     dp[0]=pw[0]=1;
     8     scanf("%d%d",&n,&m);
     9     for(int i=1,x,y;i<=m;++i)scanf("%d%d",&x,&y),link(x,y);
    10     for(int st=1;st<1<<n;++st)sz[st]=sz[st^st&-st]+1;
    11     for(int i=1;i<=n;++i)re[1<<i-1]=i;
    12     for(int i=1;i<=100;++i)pw[i]=(pw[i-1]<<1)%mod;
    13     for(int i=1;i<=n;++i)for(int j=fir[i];j;j=l[j])pre[i]|=1<<to[j]-1;
    14     for(int st=0;st<1<<n;++st)
    15         for(int U=(~st)&(1<<n)-1,S=U;S;(--S)&=U){
    16             int cnt=0;
    17             for(int i=st;i;i^=i&-i)cnt+=sz[S&pre[re[i&-i]]];
    18             (dp[st|S]+=dp[st]*pw[cnt]*(sz[S]&1?1:-1)%mod+mod)%=mod;
    19         }
    20     printf("%lld
    ",dp[(1<<n)-1]);
    21 }
    View Code

    思路积累:

    • DAG-dp:拓扑序的状态压缩
    • 神奇容斥

    T3:太阳神

    40%的暴力写在黑板上了,其实不M的话是60,附个代码。

     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 int n,pr[30000005],md[100000005],prcnt;
     5 bool np[100000005];long long Ans=1;short ans[100000001],mdcnt[100000001];
     6 int main(){
     7     scanf("%d",&n);
     8     for(int i=2;i<=n;++i){
     9         if(!np[i])ans[i]=3,pr[++prcnt]=i,mdcnt[i]=1,md[i]=i;
    10         for(int j=1;j<=prcnt&&i*pr[j]<=n;++j){
    11             int T=i*pr[j];
    12             md[T]=pr[j];np[T]=1;
    13             mdcnt[T]=md[i]==pr[j]?mdcnt[i]+1:1;
    14             ans[T]=ans[i]/(mdcnt[T]*2-1)*(mdcnt[T]*2+1);
    15             if(i%pr[j]==0)break;
    16         }
    17     }
    18     for(int i=2;i<=n;++i)Ans+=ans[i];
    19     printf("%lld
    ",(1ll*n*n-Ans)%1000000007);
    20 }
    View Code

    另一种40~60的打法是cbx的,在下面说。

    第一鸡房的不少都是用反演A的,我太菜我不会。

    我跟cbx走的。

    疯狂的数论分块就好了。

    问题就是怎么求下发题解里的f函数,求出f值后就可以在外层数论分块n/d做了。

    观察f数组,把它差分一下得到g,g[k]是什么含义?

    是[gcd(a,b)==1]×a×b==k的a,b对数。

    考虑含义,既然乘积一定,那么把k分解质因数之后把因子分配给ab就好了。

    如果一种因子有多个,那么一定只分给ab里的一个,否则gcd不为1。

    那么其实g[k]的值就是2k的质因子(不是个数)。可以线筛

    然后做一遍前缀和就可以得到f了。

    怎么求S函数呢?一个比较直接的数论分块。

    然后对于大的f值就可以递归求了。

    没有想象的那么难,虽然不是很会证。

     1 #include<cstdio>
     2 #define int long long
     3 #define mod 1000000007
     4 int pr[8000005],md[10000005],prcnt,f[10000005];
     5 bool np[10000005];int n,Ans;
     6 int S(int k){
     7     int ans=0;
     8     for(int i=1,lst;i<=k;i=lst+1)lst=k/(k/i),(ans+=(lst-i+1)%mod*(k/i))%=mod;
     9     return ans;
    10 }
    11 int F(int k){
    12     if(k<=10000000)return f[k];int ans=0;
    13     for(int j=2;j*j<=k;++j)(ans+=F(k/j/j))%=mod;
    14     return (S(k)-ans+mod)%mod;
    15 }
    16 main(){
    17     scanf("%lld",&n);f[1]=1;
    18     for(int i=2;i<=10000000;++i){
    19         if(!np[i])f[i]=2,pr[++prcnt]=i,md[i]=i;
    20         for(int j=1;j<=prcnt&&i*pr[j]<=10000000;++j){
    21             int T=i*pr[j];
    22             md[T]=pr[j];np[T]=1;
    23             f[T]=(f[i]<<(md[i]!=pr[j]))%mod;
    24             if(i%pr[j]==0)break;
    25         }
    26     }
    27     for(int i=2;i<=10000000;++i)(f[i]+=f[i-1])%=mod;
    28     for(int i=1,lst;i<=n;i=lst+1)lst=n/(n/i),(Ans+=(lst-i+1)%mod*F(n/i)+mod)%=mod;
    29     printf("%lld
    ",(n%mod*(n%mod)%mod-Ans+mod)%mod);
    30 }
    View Code

    思路积累:

    • 数论分块:竟然是联赛知识点啊
    • 线筛:肯定是联赛知识点
  • 相关阅读:
    POJ2286 The Rotation Game
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11619374.html
Copyright © 2011-2022 走看看