NOIP模拟题 2015.8.2 T3
NOIP模拟题 2015.8.6 T3

NOIP模拟题 2015.8.2 T1

HJWJBSR posted @ 2015年8月16日 22:28 in 题解 , 356 阅读

题解:考场上面感觉这就是个容斥,于是一直在推式子,一直推到考试结束= =后来讲题才知道这是个DP,设ai,j代表第i轮那个人选数后gcd变成j的概率,然后用j和所有数做一次gcd,然后就可以转移了,但是其中有i个gcd为j的不能转移。然后第二问就可以直接SG搞了,复杂度n^2m

P.S.不知道为毛用SmartC++调试了一下之后代码在sublime里面就不能看了= =

后来手动加空格总算是好了些了

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 305
#define M 1050
int n,m,sg[N][M],g[M][M],v[N],b[M],st=0;double s[N][M],ans=0;
inline int Read()
 {
    int x=0;char y;
    do y=getchar(); while (y<'0'||y>'9');
    do x=x*10+y-'0',y=getchar(); while (y>='0'&&y<='9');
    return x;
 }
int gcd(int x,int y)
 {
    if (g[x][y])
     return g[x][y];else
       return g[x][y]=(y?gcd(y,x%y):x);
 }
void Down(int x,int y)
 {
    if (!s[x][y]) return;
    int w=0,e=0;double q=s[x][y]/(n-x);
    for (int i=1;i<=n;i++)
     {
      	e=gcd(y,v[i]);
      	if (e==y) w++;else
         if (e!=1) s[x+1][e]+=q;else
           ans+=(x&1)*q;
     }
    s[x+1][y]+=q*(w-x);
 }
void Solve(int x,int y)
 {
    if (!s[x][y]) return;
    int k=0;st++;
    for (int i=1;i<=n;i++)
     {
        if (g[y][v[i]]==y) k++;else
     	  if (g[y][v[i]]!=1) b[sg[x+1][g[y][v[i]]]]=st;
     }
    if (k!=x) b[sg[x+1][y]]=st;
    for (int i=0;i<=n;i++)
     if (b[i]!=st) {sg[x][y]=i;return;}
 }
int main()
 {
    freopen("game.in","r",stdin);freopen("game.out","w",stdout);
    n=Read();
    for (int i=1;i<=n;i++) v[i]=Read();
    s[0][0]=1;Down(0,0);
    for (int i=1;i<n;i++)
     for (int j=1;j<=1000;j++)
       Down(i,j);
    if (n&1)
     for (int i=1;i<=1000;i++) ans+=s[n][i];
    printf("%.9lf ",ans);
    for (int i=n;i>0;i--)
     for (int j=1000;j>=1;j--)
       Solve(i,j);Solve(0,0);
    if (sg[0][0]) puts("1.000000000");else
      puts("0.000000000");
    return 0;
 }

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter