我永远喜欢39号同学2018。
先理解题意,其实就是用若干条线段完全覆盖
最暴力的方法是直接枚举这些线段选不选。复杂度
首先将所有区间按右端点排序。可以顺序枚举右端点,再枚举左端点看是否互质。
对于搜索的优化方法很容易想到dp。设
当
当
所以用代码写就是:
f[i+1][j]=(f[i+1][j]+f[i][j])%mod;
if(a[i+1].l<=j){
f[i+1][a[i+1].r]=(f[i+1][a[i+1].r]+f[i][j])%mod;
}else{
f[i+1][j]=(f[i+1][j]+f[i][j])%mod;
}
为什么当
完整代码:
#include<iostream>
using namespace std;
struct xyq{
int l,r;
}a[1000005];
int gcd(int a,int b){
if(!b){
return a;
}
return gcd(b,a%b);
};
long long f[1005][1005];
#define mod 1000000000
int main(){
int n,i,j,tot=0,ykb;
cin>>n;
for(i=1;i<=n;i++){
for(j=1;j<i;j++){
if(gcd(j,i)==1){
a[tot].l=j;
a[tot].r=i;
tot++;
}
}
}
f[0][a[0].r]=f[0][1]=1;
for(i=0;i<tot-1;i++){
for(j=1;j<=n;j++){
f[i+1][j]=(f[i+1][j]+f[i][j])%mod;
if(a[i+1].l<=j){
f[i+1][a[i+1].r]=(f[i+1][a[i+1].r]+f[i][j])%mod;
}else{
f[i+1][j]=(f[i+1][j]+f[i][j])%mod;
}
}
}
cout<<f[tot-1][n];
return 0;
}