zoukankan      html  css  js  c++  java
  • [Pa2013]Iloczyn

    https://www.zybuluo.com/ysner/note/1300802

    题面

    给定正整数(n)(k),问能否将(n)分解为(k)个不同正整数的乘积。

    • (nleq10^9,kleq20,Tleq4000)

    解析

    这破题目卡常,删了一堆define快一倍
    可以发现(12!=479001600>10^9)
    所以(n)顶多被分解成(11)个不同正整数。

    常规操作:找出所有约数然后(O(2^{11}))枚举加剪枝。
    然而我不会搜索啊,(TLE)了一个小时。
    要加这些剪枝。

    • 乘上后面最小的(t)(还没选的数的个数)个数大于(n),则(return)
    • 搜索过程不是枚举这个数选不选,而是枚举下一次跳到哪个数

    只加这些剪枝的后果是要去掉程序中的(define)和不必要的库(我还去了读入优化)。

    然后(bzoj)上由(TLE)变成时限一半。。。辣鸡卡常题。。。
    然后写总结时又想到一个

    • 如果(k!>n),则(continue)
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=2000;
    int n,k,sta[N],top,las,f[N][22];
    long long jc[22];
    int dfs(int x,int t,int s)
    {
      if(!t) return s==n;
      for(--t;x+t<=top;++x)
        {
          if(f[x][t]<0) return 0;
          if(1ll*f[x][t]*s>n) return 0;
          if(dfs(x+1,t,sta[x]*s)) return 1;
        }
      return 0;
    }
    int main()
    {
      ios::sync_with_stdio(false);
      int T;cin>>T;
    	jc[0]=1;for(int i=1;i<=12;++i) jc[i]=jc[i-1]*i;
      while(T--)
        {
          cin>>n>>k;top=0;
          if(jc[k]>n||k>12) {puts("NIE");continue;}
          for(int i=1;i*i<=n;++i)
            if(n%i==0)
    	  {
                sta[++top]=i;
    	    if(i*i!=n) sta[++top]=n/i;
    	  }
          sort(sta+1,sta+1+top);
          for(int i=1;i<=top;++i)
    	{
    	  long long t=1;
    	  for(int j=0;j<k&&i+j<=top;f[i][j++]=t)
    	    if(t>0)
    	    {
    	      t*=sta[i+j];
    	      if(t>n) t=-1;
    	    }
    	}
          puts(dfs(1,k,1)?"TAK":"NIE");
        }
      return 0;
    }
    
  • 相关阅读:
    Tye exception
    DataSeeder
    angular
    认证Authentication
    MVC
    Ef Core
    工作单元
    VirtualFileSystem
    中间件
    日志
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9744019.html
Copyright © 2011-2022 走看看