如果发现广告等破坏行为,请尽量将条目恢复到较早的版本而不是把相应内容直接删除,谢谢合作。

URAL/1091

来自"NOCOW"

跳转到: 导航, 搜索

枚举素数和两个素数的乘积,运用容斥原理判断.

#include <iostream>
 
using namespace std;
 
long long k,s;
long long i,j,l,ans;
 
long long prime (long long x)
{
     long long y;
     for (y=2;y<x;y++)
         if (x%y==0) return (0);
     return (1);
}
 
long long c (long long x,long long y)
{
     long long i,aa=1,bb=2;
     for (i=x-y+1;i<=x;i++)
         {
         aa*=i;
         if ((bb<=y)&&(aa%bb==0)) {
                                  aa=aa/bb;
                                  bb++;
                                  }
         }
     while (bb<=y)
           {
           aa=aa/bb;
           bb++;
           }
     return (aa);
}
 
int main ()
{
    cin>>k>>s;
    for (i=2;i<=s;i++)
        if (prime(i)) {
                      if (i*k<=s) ans+=(c(s/i,k));
                      if (ans>10000) {
                                     ans=10000;
                                     break;
                                     }
                      }
                      else {
                           l=0;
                           for (j=2;j<i;j++)
                               if ((i%j==0)&&(prime(j))&&(prime(i/j))&&(i!=j*j)) {
                                                                                 l=1;
                                                                                 break;
                                                                                 }
                           if (l==0) continue;
                           if (i*k<=s) ans-=(c(s/i,k));
                           if (ans>10000) {
                                          ans=10000;
                                          break;
                                          }
                           }
    cout<<ans<<endl;
    return (0);
}

long long c (long long x,long long y)不是必需的,用杨辉三角可以dp出来。

个人觉得好像判断解的数目大于10000的方法可以再深入讨论一下……(我骗分我自豪)--Wecing 16:13 2010年7月15日 (CST)


回朔的pascal代码:

program cyd;
  var
    p:array[1..100]of boolean;
    d:array[1..30]of integer;
    i,j,k,l,m,n,a,b,c,t:longint; ans:int64;
  function gcd(a,b:int64):int64;
    var
      c:int64;
    begin
      if a<b then begin c:=a; a:=b; b:=c; end;
      while b<>0 do
        begin
          c:=b;
          b:=a mod b;
          a:=c;
        end;
      exit(a);
    end;
  function fx(n,m:longint):int64;
    var
      i:longint; ans,a,b,x,y,z:int64;
    begin
      if n<m then exit(0);
      if m=n then exit(1);
      if m=1 then exit(n);
      a:=m;
      b:=1;
      x:=1;
      y:=1;
      for i:=1 to n-m-1 do
        begin
          inc(a); inc(b);
          x:=x*a; y:=y*b;
          z:=gcd(x,y);
          x:=x div z;
          y:=y div z;
        end;
      x:=x*n;
      exit(x div y);
    end;
  procedure solve(v,x:longint; gc:int64);
    var
      j:longint;
    begin
      if v>t then
        begin
          if gc=1 then exit;
          j:=n div gc;
          inc(ans,fx(j,k)*x);
          exit;
        end;
      solve(v+1,x,gc);
      gc:=gc*d[v];
      if gc<=n then solve(v+1,0-x,gc);
    end;begin
    readln(k,n);
    i:=2;
    while true do
      begin
        while (p[i])and(i<=n) do inc(i);
        if i=n+1 then break;
        inc(t);
        d[t]:=i;
        j:=i;
        while i+j<=n do
          begin
            p[i+j]:=true;
            j:=j+i;
          end;
        inc(i);
      end;
    solve(1,-1,1);
    if ans<10000 then writeln(ans)
                 else writeln(10000);
  end.
个人工具