首页 > 其他分享 >HDU 5320 Fan Li

HDU 5320 Fan Li

时间:2022-11-09 19:36:33浏览次数:49  
标签:HDU int s1 Fan 5320 include ll dp define


Description



Fan Li (范蠡) was an ancient Chinese advisor in the state of Yue in the Spring and Autumn period. He is a successful militarist and a successful business man. He is one of the main characters of a famous Chinese proverb “卧薪尝胆”. One day, when he was training the army, he came up with an idea, if he let all the soldiers stand in a line (every soldier has a fighting capacity), what is the maximum disjoint intervals he can choose so that the greatest common divisor of all the intervals are equal, and how many ways can he choose the maximum disjoint intervals satisfy the condition. The different ways may be very large, output the answer mod 998244353.


Input



There are multiple test cases. 
Each test cases begins with an integer n, then followed n positive integers. 
1 <= n <= 100000 
All the integers are less than 2333333. 


Output



For each test case, output the number of maximum intervals and the ways of reach the maximum number.


Sample Input



3 1 2 3 5 1 2 2 2 2 3 1 2 1


Sample Output



2 1 4 1

2 3


一道比较恶心的gcd题目,询问最多分几段不想交的区间满足gcd值相等,并且询问有多少种方案。

先计算出以[1,n]为右端点的全部的gcd的值及对应范围,记为(l,ll,r,x),即左端点在[l,ll],

右端点在r的全部区间的gcd值都为x,然后按照x的大小排序,再按r的大小排序。

然后对于相同的x,我们可以用dp[i]来表示第i个点的最大分段,

我们用二分找到第一个r小于ll的点j,显然dp[i]=dp[j]+1,这样就可以统计出最大的分段。

计算方案数的话,对于全部的满足dp[i]=dp[k]+1且k<=j的点来说,分为两种,

如果这个点的r小于l,那么显然贡献为s[k]*(ll-l+1)种

如果这个点大于等于l,那么答案是s[k]*(ll-k)种,于是统计一下前缀和即可。

#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define loop(i,j,k) for (int i = j;i != -1; i = k[i])
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
#define ff first
#define ss second
#define mp(i,j) make_pair(i,j)
#define pb push_back
#define pii pair<int,LL>
#define in(x) scanf("%d", &x);
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const double eps = 1e-4;
const int INF = 0x7FFFFFFF;
const int mod = 998244353;
const int N = 1e5 + 10;
int n, x[N], sz;

int gcd(int x, int y)
{
return x%y ? gcd(y, x%y) : y;
}

struct point
{
int l, ll, r, x;
point(int l = 0, int ll = 0, int r = 0, int x = 0) :l(l), ll(ll), r(r), x(x) {};
bool operator<(const point&a) const
{
return r < a.r;
}
}p[N * 30], q[N];


int L[N], R[N], dp[N];
LL s1[N], s2[N];

bool cmp(const point &a, const point &b)
{
return a.x == b.x ? a.r < b.r : a.x < b.x;
}

void getpoint()
{
stack<pii> a, b;
sz = 1;
rep(i, 1, n)
{
a.push(mp(x[i], 1));
while (!a.empty()) b.push(mp(gcd(a.top().ff, x[i]), a.top().ss)), a.pop();
while (!b.empty())
{
pii q = b.top(); b.pop();
if (!a.empty() && a.top().ff == q.ff) q.ss += a.top().ss, a.pop();
a.push(q);
}
while (!a.empty()) b.push(a.top()), a.pop();
int bef = 0;
while (!b.empty())
{
p[sz++] = point(bef + 1, bef + b.top().ss, i, b.top().ff);
bef += b.top().ss;
a.push(b.top()), b.pop();
}
}
}

int main()
{
while (scanf("%d", &n) != EOF)
{
rep(i, 1, n) scanf("%d", &x[i]);
getpoint(); sort(p + 1, p + sz, cmp);
LL ans = 0, cnt = 0;
for (int i = 1, j = 1; i < sz; i = j)
{
int tot = L[1] = R[1] = 0;
s1[0] = s2[0] = dp[0] = 0; dp[1] = 1;
for (; j < sz&&p[i].x == p[j].x; j++) q[++tot] = p[j];
rep(k, 2, tot)
{
int g = lower_bound(q + 1, q + k, point(0, 0, q[k].ll)) - q - 1;
dp[k] = dp[g] + 1;
if (dp[k] == dp[k - 1]) L[k] = L[k - 1], R[k] = g;
else
{
L[k] = R[k] = g;
while (dp[L[k] - 1] + 1 == dp[k]) L[k]--;
}
}
rep(k, 1, tot)
{
if (dp[k] == 1) s1[k] = q[k].ll - q[k].l + 1;
else
{
int g = lower_bound(q + L[k], q + R[k] + 1, point(0, 0, q[k].l)) - q - 1;
s1[k] = 0;
if (g >= L[k]) s1[k] += (s1[g] - s1[L[k] - 1]) * (q[k].ll - q[k].l + 1);
if (g <= R[k]) s1[k] += (s1[R[k]] - s1[g]) * q[k].ll - (s2[R[k]] - s2[g]);
s1[k] %= mod;
}
if (ans < dp[k]) ans = dp[k], cnt = s1[k];
else if (ans == dp[k]) cnt += s1[k];
s2[k] = (s2[k - 1] + s1[k] * q[k].r) % mod;
s1[k] = (s1[k] + s1[k - 1]) % mod;
cnt = (cnt % mod + mod) % mod;
}
}
printf("%lld %lld\n", ans, cnt);
}
return 0;
}



标签:HDU,int,s1,Fan,5320,include,ll,dp,define
From: https://blog.51cto.com/u_15870896/5838612

相关文章

  • HDU 5399 Too Simple
    ProblemDescriptionRhasonCheunghadasimpleproblem,andaskedTeacherMaiforhelp.ButTeacherMaithoughtthisproblemwastoosimple,sometimesna......
  • HDU 5402 Travelling Salesman Problem
    ProblemDescriptionn rowsand m columns.Thereisanon-negativenumberineachcell.TeacherMaiwantstowalkfromthetopleftcorner (1,1......
  • HDU 1272 小希的迷宫
    ProblemDescription上次Gardon的迷宫城堡小希玩了很久(见ProblemB),现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向......
  • HDU 2242 考研路茫茫——空调教室
    ProblemDescription众所周知,HDU的考研教室是没有空调的,于是就苦了不少不去图书馆的考研仔们。Lele也是其中一个。而某教室旁边又摆着两个未装上的空调,更是引起人们无......
  • HDU 4041 Eliminate Witches!
    ProblemDescriptionKanameMadokaisaMagicalGirl(MahouShoujo/PuellaMagi).ThedutyofaMagicalGirlistoeliminateWitches(Majo).Thoughsoundshorrif......
  • HDU 1237 简单计算器
    ProblemDescription读入一个只包含+,-,*,/的非负整数计算表达式,计算该表达式的值。Input测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字......
  • HDU 4739 Zhuge Liang's Mines
    ProblemDescriptionIntheancientthreekingdomperiod,ZhugeLiangwasthemostfamousandsmartestmilitaryleader.HisenemywasShimaYi,whoalways......
  • HDU 3608 最长回文
    ProblemDescription给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.回文就是正反读都是一样的字符串,如aba,abba等 Inp......
  • HDU 5591 ZYB's Game
    ProblemDescription withhisclassmatesinhiking:ahostkeepsanumberin  loses,orthehostwilltellalltheplayersthatthenumbernowisbigger......
  • HDU 4433 locker
    ProblemDescriptionApasswordlockerwithNdigits,eachdigitcanberotatedto0-9circularly.Youcanrotate1-3consecutivedigitsupordownino......