[COCI2015-2016#6] PAROVI 的题解
题意
选择一些 一下互质的二元组 ,求对于任意 都不满足 和 的个数。
简化题意
因为无解的情况只发生在所有的 之间没有多余的位置用于放置 ,所以题意可以抽象成这样:
选择一些区间互质的区间 覆盖 的方案数。
思路
设计 表示前 个字符覆盖区间 的方案数。
对于 ,有一下合法的操作:
- 不选择第 个线段,即 。
- 选择第 条线段并且第 条线段的左端点可以覆盖到 ,即 。
- 选择第 条线段并且第 条线段的左端点不可以覆盖到 ,对答案覆盖的右端点没有贡献,即 。
假线段数量一共有 条,那么答案就是 ,时间复杂度为 。
AC Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=405,mod=1e9;
struct node{int x,y;};
vector<node> v;
bool cmp(node a,node b){
if(a.y==b.y) return a.x<b.x;
return a.y<b.y;
}int n,f[N][30],ans;
signed main(){
cin>>n;
for(int i=1;i<=n;i++) for(int j=1;j<i;j++) if(__gcd(i,j)==1) v.push_back({j,i});
sort(v.begin(),v.end(),cmp);
f[0][1]=1;
for(int i=1;i<=v.size();i++){
for(int j=0;j<=n;j++){
(f[i][j]+=f[i-1][j])%=mod;
if(v[i-1].x<=j&&j<=v[i-1].y) (f[i][v[i-1].y]+=f[i-1][j])%=mod;
if(j<v[i-1].x) (f[i][j]+=f[i-1][j])%=mod;
}
}cout<<f[v.size()][n];
return 0;
}