题解:
期望递推,不关心具体位置,所以\(F[i][j]\)表示还有\(i\),\(j\)行,列未完;
\(code\):
#include<cstdio>
#include<algorithm>
#include<ctype.h>
#include<vector>
#include<queue>
#include<cstring>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
#include<map>
#include<stdlib.h>
#include<ctime>
#define mod 19260817
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
}
int n,m;
int hang,lie;
ld f[2005][2005];
bool heng[2005],zong[2005];
ld dfs(int x,int y)
{
if(f[x][y]!=-1) return f[x][y];
if(!x&&!y) return f[x][y]=0.0;f[x][y]=0.0;
f[x][y]+=(x)?(dfs(x-1,y)*1.0*x*(n-y)):0.0;
// printf("%.2lf\n",f[x][y]);
f[x][y]+=(y)?(dfs(x,y-1)*1.0*y*(n-x)):0.0;
f[x][y]+=(x&&y)?(dfs(x-1,y-1)*1.0*x*y):0.0;
return f[x][y]=(f[x][y]+n*n*1.0)/((x+y)*n-x*y);
}
int main()
{
read(n),read(m);
for(int i=1;i<=m;i++)
{
int x,y;
read(x),read(y);
heng[x]=zong[y]=1;
}
for(int i=1;i<=n;i++) hang+=!heng[i],lie+=!zong[i];
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
f[i][j]=-1;
printf("%.2lf",dfs(hang,lie));
return 0;
}
题解:
卡特兰数+质因数分解
\(code:\)
#include<cstdio>
#include<algorithm>
#include<ctype.h>
#include<vector>
#include<queue>
#include<cstring>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
#include<map>
#include<stdlib.h>
#include<ctime>
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
}
const int maxn=1000002;
ll pri[maxn<<1],phi[maxn<<1],s[maxn<<1],ans=1;
ll n,mod,tot;
bool book[maxn<<1];
void modify(int x,int d){
while(1){
if(pri[phi[x]]==0) break;
s[phi[x]]+=d;
x/=pri[phi[x]];
}
}
void sent(){
for(int i=2;i<=n<<1;i++){
if(!book[i]) pri[++tot]=i,phi[i]=tot;
for (int j=1;pri[j]*i<=(n<<1)&&j<=tot;j++){
book[pri[j]*i]=1,phi[pri[j]*i]=j;
if(i%pri[j]==0) break;
}
}
}
int main(){
// 1 1 5 14 42
// freopen("interesting.in","r",stdin);
// freopen("interesting.out","w",stdout);
read(n),read(mod);sent();
for (int i=n<<1;i>n;i--) modify(i,1);
for (int i=1;i<=n;i++) modify(i,-1);
modify(n+1,-1);
for(int i=1;i<=tot;i++)
while(s[i]--) ans=(ans*pri[i])%mod;
printf("%lld",ans);
return 0;
}
题解:
·手推可得\(d(a,b)=div(a)+div(b)-div(gcd(a,b))*2\),\(div\)为\(a,b\)的质因数指数和;
·\(O(N^2)\)暴力肯定是不可行的,因为质因数个数最多\(200\)多个,因此我们考虑枚举\(gcd\);
·我们用\(f1[k],f2[k]\)分别记下当某数为\(k\)倍数时的最小编号,次小编号;
(因为编号不可为同一个数)
·统计答案时,显然这时\(div(x)\)为定值,\(O(\sqrt{N})\)分解质因数,统计记录最小的\(div(k)-div(x)*2\)的值,更新最小编号\(id=min(id,k)\);
(其中\(k=(f1[x]==i)?f2[x]:f1[x]\);\(x\)为枚举出的因数)
\(code:\)
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=1000002;
int n,a[maxn],tot;
int pri[maxn],cnt[maxn];
int f1[maxn],f2[maxn];
bool book[maxn];
void sent()
{
for(int i=2;i<=maxn-1;i++)
{
if(!book[i])
{
pri[++tot]=i;
cnt[i]=1;
}
for(int j=1;j<=tot&&i*pri[j]<=maxn-1;j++)
{
book[i*pri[j]]=1,cnt[i*pri[j]]=cnt[i]+1;
if(i%pri[j]==0) break;
}
}
}
void update(int i,int gcd)
{
if(cnt[a[i]]<=cnt[a[f1[gcd]]])
f2[gcd]=f1[gcd],f1[gcd]=i;
else if(cnt[a[i]]<=cnt[a[f2[gcd]]]) f2[gcd]=i;
}
void getf()
{
for(int i=n;i>=1;i--)
{
for(int j=1;j*j<=a[i];j++)
if(a[i]%j==0)
{
update(i,j);
if(j*j!=a[i]) update(i,a[i]/j);
}
}
}
int main()
{
sent();
scanf("%d",&n);cnt[0]=1e9;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);getf();
for(int i=1;i<=n;i++)
{
int id=1e9,ans=1e9;
for(int j=1;j*j<=a[i];j++)
if(a[i]%j==0)
{
int x=j,k;
if(f1[x]!=i) k=f1[x];else k=f2[x];
if(ans>cnt[a[k]]-(cnt[x]<<1)||((ans==cnt[a[k]]-(cnt[x]<<1))&&id>k))
ans=cnt[a[k]]-(cnt[x]<<1),id=k;
if(j*j==a[i]) continue;
x=a[i]/j;
if(f1[x]!=i) k=f1[x];else k=f2[x];
if(ans>cnt[a[k]]-(cnt[x]<<1)||((ans==cnt[a[k]]-(cnt[x]<<1))&&id>k))
ans=cnt[a[k]]-(cnt[x]<<1),id=k;
}
printf("%d\n",id);
}
}