Codeforces Round #641 (Div. 2) 参与排名人数11937
[codeforces 1350B] Orac and Models 约数+深搜dfs
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址http://codeforces.com/contest/1350/problem/B
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
B - Orac and Models | GNU C++17 | Accepted | 452 ms | 24400 KB |
没想到第二题,就有如此难度,感觉此题难度介于AtCoder的(ABC比赛)的C题与D题之间。
基本思路,从位置最大值开始,枚举相应约数,看是否符合题意,若符合,则参与计数。
100000的约数,30个不到,故,找到1-100000的所有约数100000*30=3*10^6不超时,事先算出所有约数,
再具体根据约数,找到较小位置的数据,看是否符合题意,能否参与计数。
样例模拟如下
4
5 3 4 6
位置1 2 3 4
数值5 3 4 6
从位置4开始
a[4]=6>a[2]=3 计数2
a[4]=6>a[1]=5 计数2
a[3]=4<a[1]=5
a[2]=3<a[1]=5
最大计数值是2
7
1 4 2 3 6 4 9
位置1 2 3 4 5 6 7
数值1 4 2 3 6 4 9
a[7]=9>a[1]=1 计数2
a[6]=4>a[3]=2>a[1]=1 计数3
a[6]=4>a[1]=1 计数2
a[5]=6>a[1]=1 计数2
a[4]=3>a[1]=2 计数2
a[3]=2>a[1]=1 计数2
a[2]=4>a[1]=1 计数2
最大计数值是3
5
5 4 3 2 1
位置1 2 3 4 5
数值5 4 3 2 1
最大计数值是1
1
9
最大计数值是1
AC代码如下
#include <cstdio>
#include <algorithm>
#define maxn 100010
using namespace std;
int a[maxn],b[maxn][50],bn[maxn],tot=0,cnt[maxn];
void dfs(int step,int now){//step记录当前步数,now表示当前位置的值
int i,c;
for(i=1;i<=bn[now];i++){
c=b[now][i];//c是now的约数
if(a[now]>a[c])cnt[step]=cnt[step-1]+1,tot=max(tot,cnt[step]),dfs(step+1,c);//符合题意,计数cnt[]加1
}
}
int main(){
int t,n,i,j,pre;
for(i=1;i<=100000;i++)
for(j=1;j*j<=i;j++)
if(i%j==0){
bn[i]++;
b[i][bn[i]]=j;//表示i在bn[i]处的约数是j
if(i/j!=j)bn[i]++,b[i][bn[i]]=i/j;//bn[i]统计i的约数个数
}
scanf("%d",&t);
while(t--){
tot=1;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=n;i>=1;i--)
cnt[0]=1,dfs(1,i);
printf("%d\n",tot);
}
return 0;
}
方法二:神奇的动归dp,像最长上升子序列
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
B - Orac and Models | GNU C++17 | Accepted | 62 ms | 4400 KB |
样例数据处理过程如下
i=1 j=1
i=1 j=2
i=1 j=3
i=1 j=4
i=2 j=2
i=2 j=4
i=3 j=3
i=4 j=4
2
i=1 j=1
i=1 j=2
i=1 j=3
i=1 j=4
i=1 j=5
i=1 j=6
i=1 j=7
i=2 j=2
i=2 j=4
i=2 j=6
i=3 j=3
i=3 j=6
i=4 j=4
i=5 j=5
i=6 j=6
i=7 j=7
3
i=1 j=1
i=1 j=2
i=1 j=3
i=1 j=4
i=1 j=5
i=2 j=2
i=2 j=4
i=3 j=3
i=4 j=4
i=5 j=5
1
i=1 j=1
1
AC代码如下
#include <cstdio>
#include <algorithm>
#define maxn 100010
using namespace std;
int a[maxn],dp[maxn],ans;
int main(){
int t,n,i,j;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=1;i<=n;i++)dp[i]=1;
ans=0;
for(i=1;i<=n;i++)//i是约数,约数逐渐变大
for(j=i;j<=n;j+=i)//j%i==0
if(a[i]<a[j])dp[j]=max(dp[j],dp[i]+1);
for(i=1;i<=n;i++)ans=max(ans,dp[i]);
printf("%d\n",ans);
}
return 0;
}