time limit:1000ms memory limit:128mb
題目描述
lyk有一本書,上面有很多有趣的oi問題。今天lyk看到了這麼一道題目:
這裡有乙個長度為n的正整數數列ai(下標為1~n)。並且有乙個引數k。
你需要找兩個正整數x,y,使得x+k<=y,並且y+k-1<=n。並且要求a[x]+a[x+1]+…+a[x+k-1]+a[y]+a[y+1]+…+a[y+k-1]最大。
k<=n/2
lyk並不會做,於是它把題扔給了你。
輸入格式(max.in)
第一行兩個數n,k。
第二行n個數,表示ai。
輸出格式(max.out)
兩個數表示x,y。若有很多種滿足要求的答案,輸出x最小的值,若x最小仍然還有很多種滿足要求的答案,輸出y最小的值。
輸入樣例
5 2
6 1 1 6 2
輸出樣例
1 4
對於30%的資料n<=100。
對於60%的資料n<=1000
對於100%的資料1<=n<=100000,1<=k<=n/2,1<=ai<=10^9。.
//考場爆零** ==> 本場比賽直接gg 120 分 草草收場
#include
#include
#include
#include
using
namespace
std;
inline
void read(int &x)
while(c>='0'&&c<='9') x*=f;
}#define maxn 100005
int n,k,a[maxn];
long
long sum[maxn];
int main(int argc,char *argv)
for(register
int i=1;i<=n;++i)
for(register
int j=i+k;j+k-1
<=n;++j)
if(sum[i+k-1]-sum[i-1]+sum[j+k-1]-sum[j-1]>max)
printf("%d %d\n",ansi,ansj);
fclose(stdin);fclose(stdout);
return
0;}
分析:乙個o(n^3)的做法,直接列舉兩個區間,再列舉求區間和.因為用到了區間和,所以可以用字首和優化到o(n^2).然後可以發現這個區間長度是固定的,我們可以在挪動右端點的時候右邊每加乙個數,左邊彈乙個數,用o(n)的時間處理出每一段長度為k的區間的和,在處理的過程中可以順便記錄j-k之前的區間最大值,一邊求和一邊統計答案就可以了。
#include
#include
#include
using
namespace
std;
typedef
long
long ll;
int n,k,lastt=1,x,y;
ll a[100010],r[100010],sum,ans,max;
int main(int argc,char *argv)
}printf("%d %d\n",x,y);
fclose(stdin);fclose(stdout);
return
0;}
time limit:2000ms memory limit:1024mb
題目描述
乙個神秘的村莊裡有4家美食店。這四家店分別有a,b,c,d種不同的美食。lyk想在每一家店都吃其中一種美食。每種美食需要吃的時間可能是不一樣的。
現在給定第1家店a種不同的美食所需要吃的時間a1,a2,…,aa。
給定第2家店b種不同的美食所需要吃的時間b1,b2,…,bb。
以及c和d。
lyk擁有n個時間,問它有幾種吃的方案。
輸入格式(eat.in)
第一行5個數分別表示n,a,b,c,d。
第二行a個數分別表示ai。
第三行b個數分別表示bi。
第四行c個數分別表示ci。
第五行d個數分別表示di。
輸出格式(eat.out)
乙個數表示答案。
輸入樣例
11 3 1 1 1
4 5 6
3 2
1 輸出樣例
2 對於30%的資料a,b,c,d<=50
對於另外30%的資料n<=1000。
對於100%的資料1<=n<=100000000,1<=a,b,c,d<=5000,0<=ai,bi,ci,di<=100000000。
演算法剖析:meet in the middle
#include
#include
#include
#include
using
namespace
std;
typedef
long
long ll;
#define maxn 5050
int a[maxn],c[maxn],d[maxn],b[maxn];
int f[100000005],c1[25000010],c2[25000010],cnt1,cnt2;
ll ans=0;
inline
void read(int &x)
while(c>='0'&&c<='9') x*=f;
}int main(int argc,char *argv)
for(int i=0; i<=maxn; ++i)
while(f[i]) --f[i],c1[++cnt1]=i;
maxn = 0;
for(int i=1; i<=c; ++i)
for(int j=1; j<=d; ++j)
if(c[i] + d[j] <= n)
for(int i=0; i<=maxn; ++i)
while(f[i]) --f[i],c2[++cnt2]=i;
for(cur = cnt2; cur>=1; --cur)
if(c1[1] + c2[cur] <= n) break;
ll ans = 0;
for(int i=1; i<=cnt1; ++i)
printf("%i64d\n",ans);
fclose(stdin);fclose(stdout);
return
0;}
time limit:1000ms memory limit:128mb
題目描述
總共有n顆糖果,有3個小朋友分別叫做l,y,k。每個小朋友想拿到至少k顆糖果,但這三個小朋友有乙個共同的特點:對3反感。也就是說,如果某個小朋友拿到3顆,13顆,31顆,333顆這樣數量的糖果,他就會不開心。(也即它拿到的糖果數量不包含有一位是3)
lyk掌管著這n顆糖果,它想問你有多少種合理的分配方案使得將這n顆糖果全部分給小朋友且沒有小朋友不開心。
例如當n=3,k=1時只有1種分配方案,當n=4,k=1時有3種分配方案分別是112,121,211。當n=7,k=2時則不存在任何一種合法的方案。
當然這個答案可能會很大,你只需輸出答案對12345647取模後的結果就可以了。
輸入格式(candy.in)
第一行兩個數表示n,k。
輸出格式(candy.out)
乙個數表示方案總數。
輸入樣例
99999 1
輸出樣例
9521331
對於30%的資料n<=100
對於50%的資料n<=1000。
對於另外30%的資料k=1。
對於100%的資料3<=n<=10^10000,1<=k<=n/3,且n,k不包含前導0。
前面50分暴力,兩層資料直接不是乙個等級。。。
分析:這道題也不是一道特別簡單的數字dp,因為要3個數的和等於n,所以我們可以在每一數字的時候列舉3個數上的這一位的值,它們的和與n的第i位相差是≤2的,因為進製最多進兩位。同時還有≥k這個限制,所以我們可以設狀態f[i][j][kk][l][p]表示前i位,第i+1位要向第i位進j位,kk,l,p表示列舉的3個數是否》k.每次遞推的時候就能知道下乙個狀態,就能夠就行轉移了。
要求方案數,數字位數又這麼多,能想到的演算法只有數字dp了,從數字看向數字,是一種很好的思想的轉變,如果數字dp有數字大小的限制,那麼通用的辦法就是加一維表示是否超出限制即可。(腿老師【張浩威】出題就是有水平啊)
//數字dp
#include
#include
#include
#include
using
namespace
std;
const
int mod = 12345647;
char n[10010], k[10010];
int a[10010],b[10010],f[10010][3][2][2][2];
int main()
for (int i = 0; i <= 1; i++)
for (int j = 0; j <= 1; j++)
for (int k = 0; k <= 1; k++)
printf("%d\n", ans);
fclose(stdin);fclose(stdout);
return
0;}
2017 10 5 清北刷題衝刺班p m
對每個聯通塊單獨考慮。每個聯通塊是乙個環套樹,樹邊拎出來可以隨意定向,記樹邊為 m,所以樹的方案數為2 m 對於環來說只有兩種方向,順時針和逆時針,記環邊為 n,所以環的方案就是 2 n 2。最後把每個聯通塊的方案乘起來即可。注意,自環無論如何定向都是環,但這並不違反環的公式,故可以不特判。incl...
2017 10 3 清北刷題衝刺班p m
問題描述 你是能看到第一題的 friends 呢。hja 給你乙個只有小括號和中括號和大括號的括號序列,問該序列是否合法。輸入格式 一行乙個括號序列。輸出格式 如果合法,輸出 ok,否則輸出 wrong。樣例輸入 樣例輸出 wrong 資料範圍與規定 70 的資料,1 100。對於100 的資料,1...
清北 Noip 2016 考前刷題衝刺濟南班
2016 10 29 週六 第一天 zhx大神 上午,60分,下午,爆零orz 2016 10 30 周天 第二天 炒雞倒霉的一天 zhx大神 據大神第一天的題最簡單。上午,和數學有關,還要推理,轉化思想,把複雜的題簡單化 可是我笨qaq 95分 下午,130 2016 10 31 周一 第三天 換...