poao899 28K 4840MS G++ 0.36K 2010-03-31 02:50:18 .
頗有趣的DP。
雷:
狀態存法 dp[n大小][該序列尾數] 但是這樣是10^8記憶體會爆炸
所以滾動。
另外是%100000007所以小心溢位。
轉移方式: dp[i-1][k] + 結尾k or k+1 以及 開頭+1~k
//*******************************
#include<stdio.h>
#define MODE 100000007
int dp[10010], n, t;
long long tmp;
int main(){
scanf("%d", &n);
dp[1]= 1;
for(int i=2; i<=n; i++){
for(int j=i; j>0; j--){
dp[j+1]+= dp[j];
dp[j+1]%= MODE;
tmp= (long long)dp[j]*j;
dp[j]= (int)(tmp%MODE);
}
}
for(int i=1; i<=n; i++){
t+= dp[i];
t%= MODE;
}
printf("%d\n", t);
}
2010年3月30日 星期二
POI - PA 2006 Crayfish (精神+翻譯)
沒co出來的有趣圖論 .
Round 4的題目好有趣但是好難orz
//*************************************
翻譯
給你一張有向圖,n<=10^4個頂點,m<=10^5條邊
有些邊是特殊的邊。
現在假設我拿i為起點,一開始只能逆的走(i.e. a->b的邊只能從b走到a)
然後每經過一次特殊邊就得換方向(正走-> 逆走 反之亦然)
問你對於每個點的val值,val值定義為 從該點出發並要回到該點最多能經過多少其他的點
Input:
//***********************************
雷:
把除了特殊的邊以外的正向圖及反向圖皆分別建出來,
每一條特殊的邊ex: a -> b
那麼就會從正向圖的a和反向圖的b做雙向邊
建完圖後SCC, 判重(同時走過一個點的正向跟反向)
//************************************
Round 4的題目好有趣但是好難orz
//*************************************
翻譯
給你一張有向圖,n<=10^4個頂點,m<=10^5條邊
有些邊是特殊的邊。
現在假設我拿i為起點,一開始只能逆的走(i.e. a->b的邊只能從b走到a)
然後每經過一次特殊邊就得換方向(正走-> 逆走 反之亦然)
問你對於每個點的val值,val值定義為 從該點出發並要回到該點最多能經過多少其他的點
Input:
5 5
2 1 1
2 3 0
3 4 0
4 2 0
5 3 1
Output:
3
3
3
3
0
//***********************************
雷:
把除了特殊的邊以外的正向圖及反向圖皆分別建出來,
每一條特殊的邊ex: a -> b
那麼就會從正向圖的a和反向圖的b做雙向邊
建完圖後SCC, 判重(同時走過一個點的正向跟反向)
//************************************
POI - PA 2007 Encyclopedia [B]
30-03-10 11:10 Encyclopedia [B] OK 10 .
頗白癡的題目我說= =
說實話有點不值得Round 3的水準
就是給你一個由n個1 n個0組成的序列,每次交換相鄰兩個
問你把它轉成101010.... 或010101.... 最少要幾步
//***********************************
頗白癡的題目我說= =
說實話有點不值得Round 3的水準
就是給你一個由n個1 n個0組成的序列,每次交換相鄰兩個
問你把它轉成101010.... 或010101.... 最少要幾步
//***********************************
#include<stdio.h>
int in, n, pos, pos2;
long long ans, ans2;
long long abs(int a, int b){
if(a> b)return (long long)a-b;
return (long long)b-a;
}
int main(){
scanf("%d", &n);
pos= 1; pos2= 1;
for(int i=0; i<2*n; i++){
scanf("%d", &in);
if(in== 0){
ans+= abs(pos, i);
pos+= 2;
}else{
ans2+= abs(pos2, i);
pos2+= 2;
}
}
printf("%lld\n", ans<ans2? ans: ans2);
}
2010年3月29日 星期一
POI - PA 2008 Diagonals [B]
| User: | Chen Kuei-yi (poao899) |
| Date: | 2010-03-30 03:44:39 |
| Points | 10 |
| Comment: | Algorithmic Engagements 2008, Round 3 |
| Task: | prz/Diagonals [B] |
| Date: | 2010-03-30 05:04:08 |
| Points: | 10/10 |
| Files: | solution |
|
不對啊AC沒道理啊 O(m lg m)sort +O(n)stack
m<=10^7, n<=10^6
怎麼看都不會AC的複雜度
還有拿掉gn跑得比較快ˊˋ
勝利得一點都不開心orz
對了,測資大概灌水兩倍
//*****************************************
#include<algorithm>
#define M 5000010
int n,m,q[M],r;
struct dia{
int i, j, o;
void get(int oo){
scanf("%d%d", &i, &j); o=oo;
if(i>j){i^=j^=i^=j;}
}
bool operator< (const dia &b)const{
return i<b.i || i==b.i&&j>b.j;
}
}d[M];
struct dia2{
int i, j, o;
void set(int ii, int jj, int oo){
i=ii; j=jj; o=oo;
}
bool operator< (const dia2 &b)const{
return j<b.j || j==b.j&&i>b.i;
}
}d2[M];
int main(){
scanf("%d%d", &n, &m);
if(m>M)m=M;
for(int i=0; i<m; i++){
d[i].get(i+1);
d2[i].set(d[i].i, d[i].j, i+1);
}
std::sort(d, d+m);
std::sort(d2, d2+m);
int di=0, di2=0;
for(int i=1; i<=n; i++){
for(; di2<m; di2++){
if(d2[di2].j==i){
if(q[r-1]== d2[di2].o){
r--;
}else{
printf("%d %d\n",q[r-1], d2[di2].o);
return 0;
}
}else break;
}
for(; di<m; di++){
if(d[di].i==i){
q[r]= d[di].o;
r++;
}else break;
}
}
puts("NIE");
}
TIOJ 1132 Dark Horse Escape [Greedy]
poao899 1776K 265MS G++ 0.66K 2010-03-29 19:08:07 .
反正擋他的位置一定不會比拐馬腳差...
//**********************************
反正擋他的位置一定不會比拐馬腳差...
//**********************************
#include<stdio.h>
#include<algorithm>
bool map[1011][1011];
struct horse{
int x, y;
bool operator<(const horse &b)const{
return x<b.x || x==b.x&&y<b.y;
}
void get(){
scanf("%d%d", &x, &y);
map[x][y]= 1;
}
}h[100010];
int n, cnt;
int main(){
while(~scanf("%d", &n)){
cnt= 0;
for(int i=0; i<1011; i++)
for(int j=0; j<1011; j++)
map[i][j]= 0;
for(int i=0; i<n; i++)
h[i].get();
std::sort(h, h+n);
for(int i=0; i<n; i++){
int x= h[i].x, y= h[i].y;
if(!map[x+1][y+2]&& !map[x][y+1])
{map[x+1][y+2]= 1; cnt++;}
if(!map[x+2][y+1]&& !map[x+1][y])
{map[x+2][y+1]= 1; cnt++;}
}
printf("%d\n", cnt);
}
}
2010年3月28日 星期日
TIOJ 1528 一字千金 [Tree]
poao899 4420K 6666MS G++ 2.34K 2010-03-29 13:51:35 .
本篇全部都是雷(?
阿思:就把他想成一棵樹多了8條邊,然後去枚舉就好了
說實話也不好枚舉orz
一開始很直覺的2^8= 256的枚舉
可以想一下以下這組測資
3 3
10 100 10
1 2
2 3
1 3
答案應該是100
但是3^8= 6561太大了會TLE
而且還有一組測資
3 4
10 10 10
1 2
2 3
3 1
1 2
答案絕對是10
然後下面那組真的是我自己的問題了orz
8 9
6 3 5 2 5 3 1 4
1 2
2 4
4 5
6 4
4 8
5 7
3 5
2 6
7 8
答案是18
所以就變成2^8 *(O(e)檢查 + O(v)DP)
//*******************************
#include<stdio.h>
long long dp[50100][2], max;
int deter[50100], speCnt, n, m, val[50100], a, b, ra, rb;
int root[50100], fa[50100];
int find(int a){return root[a]==a? a: root[a]=find(root[a]);}
//0= no 1= 一定要 2= 一定不能
struct edge{
int i, j;
edge *next;
}e[100100], spe[10], *p, *v[50100];
void dfs(int n){
bool can= 1;
dp[n][0]= dp[n][1]= 0;
for(edge *ptr=v[n]; ptr; ptr=ptr->next){
if(fa[n]== ptr->j)continue;
fa[ptr->j]= n;
dfs(ptr->j);
if(deter[ptr->j]== 1)
can= 0;
}
if(deter[n]!= 2&& can){
dp[n][1]= val[n];
for(edge *ptr=v[n]; ptr; ptr=ptr->next){
if(fa[n]== ptr->j)continue;
dp[n][1]+= dp[ptr->j][0];
}
}if(deter[n]!=1){
for(edge *ptr=v[n]; ptr; ptr=ptr->next){
if(fa[n]== ptr->j)continue;
if(deter[ptr->j]==2)
dp[n][0]+= dp[ptr->j][0];
else if(deter[ptr->j]==1)
dp[n][0]+= dp[ptr->j][1];
else dp[n][0]+= dp[ptr->j][0]>dp[ptr->j][1]? dp[ptr->j][0]: dp[ptr->j][1];
}
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++){
root[i]= i;
scanf("%d", val+i);
}
for(int i=0; i<m; i++){
scanf("%d%d", &a, &b);
ra= find(a);
rb= find(b);
if(ra==rb){
spe[speCnt].i=a; spe[speCnt].j=b;
speCnt++;
}else{
e[i].i=a; e[i].j=b;
p=v[a]; v[a]=&e[i]; e[i].next=p;
e[i+m].i=b; e[i+m].j=a;
p=v[b]; v[b]=&e[i+m]; e[i+m].next=p;
root[rb]= ra;
}
}
int ii= 1<<speCnt;
for(int i=0; i<ii; i++){
//init
bool can= 1;
for(int j=1; j<=n; j++)
fa[j]=j;
for(int j=0; can&& j<speCnt; j++){
if(i& (1<<j)){
deter[spe[j].i]= 2;
deter[spe[j].j]= 0;
}else{
deter[spe[j].i]= 1;
deter[spe[j].j]= 2;
}
}
for(int i=0; can&& i<m; i++)
if(deter[e[i].i]== 1&& deter[e[i].j]== 1)
can=0;
for(int i=0; can&& i<speCnt; i++)
if(deter[spe[i].i]== 1&& deter[spe[i].j]== 1)
can=0;
if(!can)continue;
dfs(root[1]);
for(int j=0; j<2; j++)
if(dp[root[1]][j]> max)
max=dp[root[1]][j];
}
printf("%I64d\n",max);
}
本篇全部都是雷(?
阿思:就把他想成一棵樹多了8條邊,然後去枚舉就好了
說實話也不好枚舉orz
一開始很直覺的2^8= 256的枚舉
可以想一下以下這組測資
3 3
10 100 10
1 2
2 3
1 3
答案應該是100
但是3^8= 6561太大了會TLE
而且還有一組測資
3 4
10 10 10
1 2
2 3
3 1
1 2
答案絕對是10
然後下面那組真的是我自己的問題了orz
8 9
6 3 5 2 5 3 1 4
1 2
2 4
4 5
6 4
4 8
5 7
3 5
2 6
7 8
答案是18
所以就變成2^8 *(O(e)檢查 + O(v)DP)
//*******************************
#include<stdio.h>
long long dp[50100][2], max;
int deter[50100], speCnt, n, m, val[50100], a, b, ra, rb;
int root[50100], fa[50100];
int find(int a){return root[a]==a? a: root[a]=find(root[a]);}
//0= no 1= 一定要 2= 一定不能
struct edge{
int i, j;
edge *next;
}e[100100], spe[10], *p, *v[50100];
void dfs(int n){
bool can= 1;
dp[n][0]= dp[n][1]= 0;
for(edge *ptr=v[n]; ptr; ptr=ptr->next){
if(fa[n]== ptr->j)continue;
fa[ptr->j]= n;
dfs(ptr->j);
if(deter[ptr->j]== 1)
can= 0;
}
if(deter[n]!= 2&& can){
dp[n][1]= val[n];
for(edge *ptr=v[n]; ptr; ptr=ptr->next){
if(fa[n]== ptr->j)continue;
dp[n][1]+= dp[ptr->j][0];
}
}if(deter[n]!=1){
for(edge *ptr=v[n]; ptr; ptr=ptr->next){
if(fa[n]== ptr->j)continue;
if(deter[ptr->j]==2)
dp[n][0]+= dp[ptr->j][0];
else if(deter[ptr->j]==1)
dp[n][0]+= dp[ptr->j][1];
else dp[n][0]+= dp[ptr->j][0]>dp[ptr->j][1]? dp[ptr->j][0]: dp[ptr->j][1];
}
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++){
root[i]= i;
scanf("%d", val+i);
}
for(int i=0; i<m; i++){
scanf("%d%d", &a, &b);
ra= find(a);
rb= find(b);
if(ra==rb){
spe[speCnt].i=a; spe[speCnt].j=b;
speCnt++;
}else{
e[i].i=a; e[i].j=b;
p=v[a]; v[a]=&e[i]; e[i].next=p;
e[i+m].i=b; e[i+m].j=a;
p=v[b]; v[b]=&e[i+m]; e[i+m].next=p;
root[rb]= ra;
}
}
int ii= 1<<speCnt;
for(int i=0; i<ii; i++){
//init
bool can= 1;
for(int j=1; j<=n; j++)
fa[j]=j;
for(int j=0; can&& j<speCnt; j++){
if(i& (1<<j)){
deter[spe[j].i]= 2;
deter[spe[j].j]= 0;
}else{
deter[spe[j].i]= 1;
deter[spe[j].j]= 2;
}
}
for(int i=0; can&& i<m; i++)
if(deter[e[i].i]== 1&& deter[e[i].j]== 1)
can=0;
for(int i=0; can&& i<speCnt; i++)
if(deter[spe[i].i]== 1&& deter[spe[i].j]== 1)
can=0;
if(!can)continue;
dfs(root[1]);
for(int j=0; j<2; j++)
if(dp[root[1]][j]> max)
max=dp[root[1]][j];
}
printf("%I64d\n",max);
}
TIOJ 1325 倍因道 - EXTREME
poao899 1948K 326MS G++ 0.89K 2010-03-29 00:10:54 .
我說code風格好醜= =
然後用1241來Debug...不行 思路不夠清楚
O(n ln n)+ T*O(1)
//**************************
#include<stdio.h>
#include<algorithm>
#define MAX 100000
struct stuff{
int ori, cmp;
bool operator<(const stuff &b)const{
return cmp<b.cmp;
}
}s[100010];
int sieve[100010], dp[100010], get[100010], t, n;
int main(){
for(int i=1; i<=MAX; i++)
for(int j=i+i; j<=MAX; j+=i)
sieve[j]++;
for(int i=1; i<=MAX; i++){
s[i-1].ori= i;
s[i-1].cmp= (sieve[i]+1)* i;
}
std::sort(s, s+MAX);
for(int i=1,j=0; i<=MAX; i++){
dp[i]= dp[i-1];
while(j<MAX&& s[j].cmp<=i){
dp[i]-= sieve[s[j].ori];
for(int z=s[j].ori*2; z<=MAX; z+=s[j].ori){
if(z<i)dp[i]++;
get[z]++;
}
j++;
}
dp[i]+= get[i];
}
scanf("%d", &t);
while(t--){
scanf("%d", &n);
printf("%d\n", dp[n]);
}
}
我說code風格好醜= =
然後用1241來Debug...不行 思路不夠清楚
O(n ln n)+ T*O(1)
//**************************
#include<stdio.h>
#include<algorithm>
#define MAX 100000
struct stuff{
int ori, cmp;
bool operator<(const stuff &b)const{
return cmp<b.cmp;
}
}s[100010];
int sieve[100010], dp[100010], get[100010], t, n;
int main(){
for(int i=1; i<=MAX; i++)
for(int j=i+i; j<=MAX; j+=i)
sieve[j]++;
for(int i=1; i<=MAX; i++){
s[i-1].ori= i;
s[i-1].cmp= (sieve[i]+1)* i;
}
std::sort(s, s+MAX);
for(int i=1,j=0; i<=MAX; i++){
dp[i]= dp[i-1];
while(j<MAX&& s[j].cmp<=i){
dp[i]-= sieve[s[j].ori];
for(int z=s[j].ori*2; z<=MAX; z+=s[j].ori){
if(z<i)dp[i]++;
get[z]++;
}
j++;
}
dp[i]+= get[i];
}
scanf("%d", &t);
while(t--){
scanf("%d", &n);
printf("%d\n", dp[n]);
}
}
訂閱:
文章 (Atom)