http://codeforces.com/contest/466
噗,b没写出来啊。a写完后过了40分钟了啊,罚时4次啊!果然太弱
总结:
a题看错题,没有考虑m>=n其实也是可行的,导致调了40min。。。b题不会。。。。。。(暴力是硬伤。。),c题一开始交了tle。。。。。。然后改了下才过。。rp好。
很多情况下2种决策取最优我们可以枚举其中一种决策的数目然后计算另一种决策的数目。。简称打暴力打到家
题意:要过n个站,每次可以选择过1个站花费a卢布,也可以选择过m个站花b卢布
方法一:枚举其中一种,另一种可直接算出。。。(噗,看了tourist的代码才发现。。。。。。。。。。。。。。。。。我是sb,论暴力的重要性)
方法二:完全背包,但是体积并不是n,,而是>=n。。。。。。。(看来我被固定思维了。。。不行。。。得治。。)
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << #x << " = " << x << endl #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; } inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } inline const int max(const int &a, const int &b) { return a>b?a:b; } inline const int min(const int &a, const int &b) { return a<b?a:b; } int n, m, a, b, ans, f[2005]; int main() { read(n); read(m); read(a); read(b); CC(f, 0x3f); f[0]=0; for1(i, 1, 2) { int v, w; if(i==1) v=1, w=a; if(i==2) v=m, w=b; for1(j, v, 2000) f[j]=min(f[j], f[j-v]+w); } ans=~0u>>1; for1(i, n, 2000) ans=min(f[i], ans); printf("%d", ans); return 0; }
题意:给你一个矩阵a×b,然后需要面积>=n*6,每次可以(任意)扩大a和b,问扩大满足>=n*6后最小的面积及其边长。
果然还是不会暴力。。。。。。看tourist的代码好像就是暴力?这种情况和a题的一样,2种决策。。扩大a和扩大b。。枚举其中一个即可。。
(还没写。。QAQ
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << #x << " = " << x << endl #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; } inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } inline const int max(const int &a, const int &b) { return a>b?a:b; } inline const int min(const int &a, const int &b) { return a<b?a:b; } long long ans=~0ull>>1, xx, yy, a, b, n; int main() { cin >> n >> a >> b; if(a*b>=n*6) { printf("%I64d %I64d %I64d ", a*b, a, b); } else { n*=6; bool flag=0; if(a>b) swap(a, b), flag=1; for(long long i=1; i<=n; ++i) { long long x=i, y=(n+x-1)/x; if(x>y) break; if(x<a) x=a; if(y<b) y=b; if(x*y<ans) { ans=x*y, xx=x, yy=y; } } if(flag) swap(xx, yy); printf("%I64d %I64d %I64d ", ans, xx, yy); } return 0; }
题意:给你n个数,分成连续的3部分,使得3部分的和相等,问分的方案数。
因为是连续的,那么一段是1~k,第二段是k+1~j,第三段是j+1~n,那么我们发现,当且1~k的和为sum{a[i]}/3的时候才考虑第二段,第三段相同
于是很容易得出
for1(i, 1, n-2) { if(sum[i]==sz) for1(j, i+1, n-1) if(sum[j]-sum[i]==sz) ++ans;
而这是n^2的,,一开始我没看题直接交。。然后tle了。。
我们发现,其实sum[i]是一定==sz的,所以在sum[j]-sum[i]==sz可以变成sum[j]==sz+sum[i]==sz*2
那么我们发现,只要维护对于每一个位置i,判断它的前缀和是否==sz×2,那么在更新的时候,答案可以直接加上i+1后边sum[j]==sz*2的数量。
即我们再维护一个前缀和表示sz*2的数量,那么位置i后的数量就为cnt[n-1]-cnt[i],这里n-1是因为还要分一段,即第三段。
#include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define rep(i, n) for(int i=0; i<(n); ++i) #define for1(i,a,n) for(int i=(a);i<=(n);++i) #define for2(i,a,n) for(int i=(a);i<(n);++i) #define for3(i,a,n) for(int i=(a);i>=(n);--i) #define for4(i,a,n) for(int i=(a);i>(n);--i) typedef long long ll; #define CC(i,a) memset(i,a,sizeof(i)) #define read(a) a=getint() #define print(a) printf("%d", a) #define dbg(x) cout << (#x) << " = " << (x) << endl #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; } inline const ll getint() { ll r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } inline const int max(const int &a, const int &b) { return a>b?a:b; } inline const int min(const int &a, const int &b) { return a<b?a:b; } const int N=5*1e5 + 100; int n; ll sum[N], cnt[N], ans, a[N]; int main() { read(n); for1(i, 1, n) read(a[i]), sum[i]=sum[i-1]+a[i]; if(sum[n]%3!=0) puts("0"); else { ll sz=sum[n]/3; for1(i, 1, n) if(sum[i]==(sz<<1)) cnt[i]=1; for1(i, 1, n) cnt[i]+=cnt[i-1]; for1(i, 1, n-2) { if(sum[i]==sz) ans+=cnt[n-1]-cnt[i]; } printf("%I64d", ans); } return 0; }