标签:its scan 多少 fine const 题目 pac 一个人 return
烤乐滋炸桥的行为被村长发现了,村长很愤怒,叫烤乐滋赔钱。可烤乐滋身上没有那么多钱,他就只好去银行取钱了。
不过你应该能够想到,作为天下养猪第一村的地方,银行肯定也是很不一般的。每个人来到银行,都有一个想要取的钱数Mi,一个排队的队是合法的,只有在你把这个队中的所有人按照Mi从小到大排序之后,每相邻的两个人当中,后一个人要取的钱数一定是前面那个人的倍数,且这两个人要取的钱数不相等。
例如:2 9 1 4 96,这个队是合法的,因为将它排序之后的1 2 4 8 96没有相邻的两个数相等,并且后面一个数总是前面一个数的倍数。
而2 8 1 3 96,这个队是不合法的,因为将它排序之后的1 2 3 8 96当中3不是2的倍数。
显然,只有1个人的序列和没有人的序列一定是合法的。
现在有n个人在排队,烤乐滋可以从中叫出来若干个人(人数可以为0..n中的任意数),使这些人按照原来在队伍中的顺序组成一个队。烤乐滋想要知道,有多少种这样的方案使得叫出来的人排起来的队是合法的。
由于这个数太大了,你需要将它对998244353取模后输出。
第一行一个数n,表示排队的人数。
第二行n个数,第i个数Mi表示排在第i个的人要取的钱。
方案数,对998244353取模。
dp+枚举因子+离散化
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+7;
int s[maxn];
ll dp[maxn];
const ll mod = 998244353;
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&s[i]);
dp[s[i]]++;
}
ll ans=0;
sort(s+1,s+1+n);
int m =(int) (unique(s+1,s+n+1) -s - 1);
for(int i=1;i<=m;++i){
ll temp=dp[s[i]];
for(int j=1;j*j<=s[i];++j){
if(s[i]%j!=0||s[i]==1) continue;
if(j*j!=s[i]){
dp[s[i]]=(dp[s[i]]+temp*dp[j]%mod)%mod;
if(j!=1)
dp[s[i]]=(dp[s[i]]+temp*dp[s[i]/j]%mod)%mod;
}
else{
dp[s[i]]=(dp[s[i]]+temp*dp[j]%mod)%mod;
}
}
ans=(ans+dp[s[i]])%mod;
}
printf("%lld\n",(ans+1)%mod);
return 0;
}
标签:its scan 多少 fine const 题目 pac 一个人 return
原文地址:https://www.cnblogs.com/smallocean/p/10204970.html