Shift Number
分析:比赛中做出最多的一道,但也确实卡了很多大牛、菜鸟。推导的过程如下图:
1 | 3 | 6 | 6 | 5 | 3 |
1 | 2 | 3 |
|
|
|
| 1 | 2 | 3 |
|
|
|
| 1 | 2 | 3 |
|
|
|
| 1 | 2 | 3 |
等价于:
1 | 3 | 6 | 6 | 5 | 3 |
1 | 1 | 1 | 1 |
|
|
| 2 | 2 | 2 | 2 |
|
|
| 3 | 3 | 3 | 3 |
发现:1111,2222,3333都是1111的倍数,于是规律就可以看出来了。
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include
<
stdio.h
>
#include < string .h >
#define LL __int64
int main()
{
LL x;
while (scanf( " %I64d " , & x) != EOF) {
if ( ! x) break ;
LL k = 1 , t;
while (k < x) k = k * 10 + 1 ;
k /= 10 ;
while (x % k != 0 ) k /= 10 ;
printf( " %I64d\n " , x / k);
}
return 0 ;
}
#include < string .h >
#define LL __int64
int main()
{
LL x;
while (scanf( " %I64d " , & x) != EOF) {
if ( ! x) break ;
LL k = 1 , t;
while (k < x) k = k * 10 + 1 ;
k /= 10 ;
while (x % k != 0 ) k /= 10 ;
printf( " %I64d\n " , x / k);
}
return 0 ;
}
Bag Problem
分析:背包。数据范围比较大,用set+map水过。后来birdfly出了一组很BT的数据,把我的程序给cha掉了。呜~
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include
<
stdio.h
>
#include < string .h >
#include < set >
#include < map >
using namespace std;
int main()
{
int n, m, k, i;
int gd[ 41 ];
// freopen("in.txt", "r", stdin);
set < int , greater < int > > mp, mp1;
map < int , int > bg;
while (scanf( " %d%d " , & n, & m) != EOF) {
scanf( " %d " , & k);
for (i = 0 ; i < k; i ++ ) {
scanf( " %d " , & gd[i]);
}
mp.clear();
mp1.clear();
bg.clear();
mp.insert( 0 );
bg[ 0 ] = 0 ;
mp1 = mp;
int w;
set < int , greater < int > > ::iterator it;
for (i = 0 ; i < k; i ++ ) {
it = mp.begin();
while (it != mp.end()) {
w = * it;
if (w + gd[i] <= m && bg[w] < n) {
mp1.insert(w + gd[i]);
bg[w + gd[i]] = bg[w] + 1 ;
}
it ++ ;
}
mp = mp1;
}
it = mp.begin();
int max =* it;
printf( " %d\n " , max);
}
return 0 ;
}
#include < string .h >
#include < set >
#include < map >
using namespace std;
int main()
{
int n, m, k, i;
int gd[ 41 ];
// freopen("in.txt", "r", stdin);
set < int , greater < int > > mp, mp1;
map < int , int > bg;
while (scanf( " %d%d " , & n, & m) != EOF) {
scanf( " %d " , & k);
for (i = 0 ; i < k; i ++ ) {
scanf( " %d " , & gd[i]);
}
mp.clear();
mp1.clear();
bg.clear();
mp.insert( 0 );
bg[ 0 ] = 0 ;
mp1 = mp;
int w;
set < int , greater < int > > ::iterator it;
for (i = 0 ; i < k; i ++ ) {
it = mp.begin();
while (it != mp.end()) {
w = * it;
if (w + gd[i] <= m && bg[w] < n) {
mp1.insert(w + gd[i]);
bg[w + gd[i]] = bg[w] + 1 ;
}
it ++ ;
}
mp = mp1;
}
it = mp.begin();
int max =* it;
printf( " %d\n " , max);
}
return 0 ;
}
Consumer
分析:背包。题目原型是 USACO DEC09 vidgame,不再赘述。
Counting Sequences
分析:DP+树状数组优化。刚好最近在学树状数组,不过跟DP结合来用还是第一次,当然是参考了别人的解题报告。
dp方程很明显, dp[i] = dp[i-1]+A, dp[i]:前i个元素的 Perfect Sub-sequences 的个数,A为以第i个元素为结尾的Perfect Sub-sequences
的个数。为了求 A,可以先将元素离散化,不用处理重复的情况。f[i] 就表示 以i结尾的Perfect Sub-sequences的个数,包括单独的i(求和的需要,也是不处理重复情况的原因)。
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include
<
stdio.h
>
#include < string .h >
#include < algorithm >
using namespace std;
#define NL 100001
#define MD 9901
struct Num {
int a, id;
bool operator < ( const Num & x) const {
return a < x.a;
}
}ent[NL];
int b[NL], dp[NL], t[NL];
int n, d;
inline int lowbit( int x)
{
return x & ( - x);
}
int sum( int x)
{
int cnt = 0 ;
while (x > 0 ) {
cnt += t[x];
x -= lowbit(x);
}
return cnt;
}
void update( int x, int c)
{
while (x <= n) {
t[x] += c;
x += lowbit(x);
}
}
int find( int x)
{
int low = 1 , high = n, mid;
int ans = 0 ;
while (low <= high) {
mid = (low + high) >> 1 ;
if (ent[mid].a > x) {
high = mid - 1 ;
} else {
ans = mid;
low = mid + 1 ;
}
}
return ans;
}
int main()
{
int i, j;
// freopen("in.txt", "r", stdin);
while (scanf( " %d%d " , & n, & d) != EOF) {
for (i = 1 ; i <= n; i ++ ) {
scanf( " %d " , & ent[i].a);
ent[i].id = i;
}
sort(ent + 1 , ent + 1 + n);
b[ent[ 1 ].id] = 1 ;
for (i = 2 ; i <= n; i ++ ) {
b[ent[i].id] = i;
}
dp[ 1 ] = 0 ;
memset(t, 0 , sizeof (t));
update(b[ 1 ], 1 );
for (i = 2 ; i <= n; i ++ ) {
int k1 = find(ent[b[i]].a + d);
int k2 = find(ent[b[i]].a - d - 1 );
int inc = sum(k1) - sum(k2);
inc = (inc + MD) % MD;
dp[i] = (dp[i - 1 ] + inc) % MD;
update(b[i], inc + 1 );
}
printf( " %d\n " , dp[n]);
}
return 0 ;
}
#include < string .h >
#include < algorithm >
using namespace std;
#define NL 100001
#define MD 9901
struct Num {
int a, id;
bool operator < ( const Num & x) const {
return a < x.a;
}
}ent[NL];
int b[NL], dp[NL], t[NL];
int n, d;
inline int lowbit( int x)
{
return x & ( - x);
}
int sum( int x)
{
int cnt = 0 ;
while (x > 0 ) {
cnt += t[x];
x -= lowbit(x);
}
return cnt;
}
void update( int x, int c)
{
while (x <= n) {
t[x] += c;
x += lowbit(x);
}
}
int find( int x)
{
int low = 1 , high = n, mid;
int ans = 0 ;
while (low <= high) {
mid = (low + high) >> 1 ;
if (ent[mid].a > x) {
high = mid - 1 ;
} else {
ans = mid;
low = mid + 1 ;
}
}
return ans;
}
int main()
{
int i, j;
// freopen("in.txt", "r", stdin);
while (scanf( " %d%d " , & n, & d) != EOF) {
for (i = 1 ; i <= n; i ++ ) {
scanf( " %d " , & ent[i].a);
ent[i].id = i;
}
sort(ent + 1 , ent + 1 + n);
b[ent[ 1 ].id] = 1 ;
for (i = 2 ; i <= n; i ++ ) {
b[ent[i].id] = i;
}
dp[ 1 ] = 0 ;
memset(t, 0 , sizeof (t));
update(b[ 1 ], 1 );
for (i = 2 ; i <= n; i ++ ) {
int k1 = find(ent[b[i]].a + d);
int k2 = find(ent[b[i]].a - d - 1 );
int inc = sum(k1) - sum(k2);
inc = (inc + MD) % MD;
dp[i] = (dp[i - 1 ] + inc) % MD;
update(b[i], inc + 1 );
}
printf( " %d\n " , dp[n]);
}
return 0 ;
}
1 | 3 | 6 | 6 | 5 | 3 |
1 | 2 | 3 |
|
|
|
| 1 | 2 | 3 |
|
|
|
| 1 | 2 | 3 |
|
|
|
| 1 | 2 | 3 |