洛谷 P 1890
阿新 • • 發佈:2018-12-16
題目是道區間dp,
用線段樹莽出來的不多談了
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 1e5+5; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 int num[maxn<<2]; int gcd(int i,int j) { return !j ? i:gcd(j,i%j); } void build(int l,int r,int rt) { if(l==r) { scanf("%d",&num[rt]); return; } int mid = (l+r)/2; build(lson); build(rson); num[rt] = gcd(num[rt<<1], num[rt<<1|1]); } int query(int L,int R,int l,int r,int rt) { if(L<=l && R>=r) return num[rt]; int temp = 0; int a1 = 0,a2 = 0; int mid = (l+r) >> 1; if(L<=mid) a1 = query(L,R,lson); if(R>mid) a2 = query(L,R,rson); temp = gcd(a1, a2); return temp; } int main() { int n,m; scanf("%d%d",&n,&m); build(1,n,1); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",query(x,y,1,n,1)); } return 0; }
之後才是重頭戲,區間dp
我們 另 dp[ i ] [ j ] 代表區間( i , j )的gcd,那麼對於每個dp[ i ] [ j ] 都有
dp[ i ] [ j ] = gcd( dp [ i ] [ j - 1 ] , dp[ j ] [ j ] ) 不斷地更新 i - j 這個區間的數。。。
( 讓 j 從 i + 1 跑到 n )
以下是 區間dp ac 程式碼。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define ll long long int using namespace std; const int maxn = 1e4+5; ll dp[maxn][maxn]; int main() { ll a,b; ll p,q; scanf("%lld%lld",&a,&b); for(int i=1;i<=a;i++) scanf("%lld",&dp[i][i]); for(int i=0;i<=a;i++) for(int j=i+1;j<=a;j++) dp[i][j]=__gcd(dp[j][j],dp[i][j-1]); for(int i=1;i<=b;i++) scanf("%lld%lld",&p,&q), printf("%lld\n",dp[p][q]); return 0; }