HDU-5400 Arithmetic Sequence(数学 || DP)
2015-08-18 18:51
477 查看
Arithmetic Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Problem Description
A sequence b1,b2,⋯,bn are
called (d1,d2)-arithmetic
sequence if and only if there exist i(1≤i≤n) such
that for every j(1≤j<i),bj+1=bj+d1 and
for every j(i≤j<n),bj+1=bj+d2.
Teacher Mai has a sequence a1,a2,⋯,an.
He wants to know how many intervals [l,r](1≤l≤r≤n) there
are that al,al+1,⋯,ar are (d1,d2)-arithmetic
sequence.
Input
There are multiple test cases.
For each test case, the first line contains three numbers n,d1,d2(1≤n≤10^5,|d1|,|d2|≤1000),
the next line contains n integers a1,a2,⋯,an(|ai|≤10^9).
Output
For each test case, print the answer.
Sample Input
5 2 -2 0 2 0 -2 0 5 2 3 2 3 3 3 3
Sample Output
12 5
法一:
和队友讨论之后,觉得每一个序列,只要其符合(①公差为d1②公差为d2③前面公差为d1,后面公差为d2)三者任意一个就满足题意
然后求出每一个最长的符合题目条件的序列,然后求其连续子序列(元素个数>=2)
假设一个最长的符合题目条件的序列的元素个数为tmp,则其连续子序列中:元素个数为tmp个的有1个,元素个数为tmp-1个的有2个……以此类推,将所有连续子序列(元素个数>=2)加起来得:((tmp-1)*tmp)/2
不能通过最长的符合题目条件的序列算出元素个数为1的子序列个数:①某一个元素单独构成一个序列(我用的方法不计入其中)②前一个最长的符合题目条件的序列的最后一个元素是下一个最长的符合题目条件的序列的第一个元素(主要原因)
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=100005; int n,a[MAXN]; int main() { int i,j,d1,d2; long long ans,tmp;//long long 才能过 while(3==scanf("%d%d%d",&n,&d1,&d2)) { for(i=0;i<n;++i) scanf("%d",a+i); ans=n; a =INF;//刚开始没有初始化a ,导致WA两次。。。 for(i=0;i<n;) { if(a[i+1]==a[i]+d1) { j=i+1; while(j<n&&a[j+1]==a[j]+d1) ++j; while(j<n&&a[j+1]==a[j]+d2) ++j; tmp=j-i+1; ans+=((tmp*(tmp-1))>>1);//答案加上每个最长符合条件的序列的连续子序列(元素个数>=2)的个数 i=j; } else if(a[i+1]==a[i]+d2) { j=i+1; while(j<n&&a[j+1]==a[j]+d2) ++j; tmp=j-i+1; ans+=((tmp*(tmp-1))>>1);//同上 i=j; } else ++i; } printf("%I64d\n",ans); } return 0; }
法二:
另一个队的大神想到了DP的解法(果然DP最简单)
#include <iostream> #include <stdio.h> using namespace std; long long a[100500]; long long f[100500][2]; long long ans; int main() { int n,d1,d2,i; while(cin >> n >> d1 >> d2){ for(i = 0; i < n; i ++) scanf("%I64d",&a[i]); ans = 1; f[0][0] = 1; f[0][1] = 0; for(i = 1; i < n; i ++){ if(a[i] - a[i-1] == d1){ f[i][0] = f[i-1][0] + 1; } else{ f[i][0] = 1; } if(a[i] - a[i-1] == d2 && d1 != d2){ f[i][1] = f[i-1][0] + f[i-1][1]; } else{ f[i][1] = 0; } ans += f[i][0]; ans += f[i][1]; } printf("%I64d\n",ans); } return 0; }
法三:
官方给出的解法:
首先预处理出来出ii这个位置向前d_1d
1的等差序列和向后d_2d2的等差数列能延续到多长,记作l_i,r_ili,ri。
如果d_1\neq
d_2
d
1≠d2,那么枚举中间位置,答案为l_i*r_ili∗ri。
如果d_1=d_2d
1=d2,枚举开始位置,答案为r_iri。
#include <cstdlib> #include <cctype> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <string> #include <iostream> #include <sstream> #include <map> #include <set> #include <queue> #include <stack> #include <fstream> #include <numeric> #include <iomanip> #include <bitset> #include <list> #include <stdexcept> #include <functional> #include <utility> #include <ctime> #include <cassert> #include <complex> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) #define ACCU accumulate #define TWO(x) (1<<(x)) #define TWOL(x) (1ll<<(x)) #define clr(a) memset(a,0,sizeof(a)) #define POSIN(x,y) (0<=(x)&&(x)<n&&0<=(y)&&(y)<m) #define PRINTC(x) cout<<"Case #"<<++__<<": "<<x<<endl #define POP(x) (__builtin_popcount(x)) #define POPL(x) (__builtin_popcountll(x)) typedef vector<int> VI; typedef vector<string> VS; typedef vector<double> VD; typedef long long ll; typedef long double LD; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; typedef vector<ll> VL; typedef vector<PII> VPII; typedef complex<double> CD; const int inf=0x20202020; const ll mod=1000000007; const double eps=1e-9; const double pi=3.1415926535897932384626; const int DX[]={1,0,-1,0},DY[]={0,1,0,-1}; ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;} // head const int N=101000; int n,d1,d2,a ,l ,r ; ll ans; int main() { while (scanf("%d%d%d",&n,&d1,&d2)!=EOF) { rep(i,0,n) scanf("%d",a+i); rep(i,0,n) if (i==0||a[i-1]+d1!=a[i]) l[i]=1; else l[i]=l[i-1]+1; per(i,0,n) if (i==n-1||a[i]+d2!=a[i+1]) r[i]=1; else r[i]=r[i+1]+1; ans=0; rep(i,0,n) if (d1!=d2) ans+=(ll)l[i]*r[i]; else ans+=r[i]; printf("%lld\n",ans); } }
相关文章推荐
- java 中break、continue、return之间的区别与联系
- hdu5400Arithmetic Sequence
- PowerBuilder中使用JDBC连接MYSQL 无法使用COUNT(*) MAX() 函数的处理
- 合成UIImageView,改变尺寸
- 使用YUI Compressor压缩JS和Css,批处理,右键,注册表,打包
- iOS UIImage剪切圆形
- UIView的“截屏”
- Mybatis select返回值为map时,选取表字段的两列作为key,value
- STL 整理(map、set、vector、list、stack、queue、deque、priority_queue)
- easyui datebox 扩展 只显示年月
- /proc/cpuinfo
- Null value was assigned to a property of primitive type setter of
- easyui数据窗口datagrid的数据加载问题
- HDU5400 Arithmetic Sequence 数学题
- UINavigation返回按钮修改标题
- iOS UITableView代理方法详解
- android.util.AndroidRuntimeException: requestFeature() must be called before adding content
- ZOJ 2319 Beatuiful People(单调递增序列的变形)
- UINavigationController
- 初始UI(UILabel、UIButton、UITextField)