Codeforces Round #263 Div.1:
B. Appleman and Tree
题目大意:给一棵树,每个点可能是黑色或白色。求有多少种方案使得这棵树被分成k份,每份有且仅有一个黑点。
一看就知道是树形dp,可是不会做...题解思路很巧妙,很有借鉴意义。用dp[v][0]表示当前点及与它同一块的点没有黑点,dp[v][1]表示当前点及与它同一块的点有且仅有一个黑点。然后就是dp了。dp时有一个技巧:当前点为白色,而我们要求dp[v][1]时,我们必须只连接一个dp[child[i]][1]。我们可以直接用dp[v][0]来得到这时候的dp[v][1]。这样做既简洁又方便。实在是很神奇!
1 //7697563 2014-09-07 04:12:28 moxiaomo B - Appleman and Tree GNU C++ Accepted 31 ms 8200 KB 2 #include <bits/stdc++.h> 3 using namespace std; 4 typedef long long LL; 5 const int maxn=100001; 6 const LL MOD=1000000007; 7 8 int pos,lin[maxn],ta[maxn],sd[maxn]; 9 inline void biu(int s,int t) { ++pos; lin[pos]=ta[s]; ta[s]=pos; sd[pos]=t; } 10 11 int n; 12 int color[maxn]; 13 LL dp[maxn][2]; 14 void dfs(int v) 15 { 16 dp[v][color[v]]=1; 17 for (int i=ta[v];i;i=lin[i]) 18 { 19 dfs(sd[i]); 20 if (color[v]==1) 21 { 22 //dp[v][0]=0; 23 dp[v][1]=dp[v][1]*(dp[sd[i]][0]+dp[sd[i]][1])%MOD; 24 } 25 else 26 { 27 dp[v][1]=dp[v][1]*(dp[sd[i]][0]+dp[sd[i]][1])%MOD; 28 dp[v][1]=(dp[v][1]+dp[v][0]*dp[sd[i]][1])%MOD; 29 dp[v][0]=dp[v][0]*(dp[sd[i]][0]+dp[sd[i]][1])%MOD;//-- 30 } 31 } 32 } 33 int main() 34 { 35 scanf("%d",&n); 36 for (int i=0,p;i<n-1;i++) scanf("%d",&p),biu(p,i+1); 37 for (int i=0;i<n;i++) scanf("%d",color+i); 38 dfs(0); 39 cout<<dp[0][1]<<endl; 40 }
C. Appleman and a Sheet of Paper
简单题。细节的地方需要好好想想。
关于mid那里为什么错还不清楚...
1 //7698314 2014-09-07 08:34:09 moxiaomo C - Appleman and a Sheet of Paper GNU C++ Accepted 62 ms 760 KB 2 //iostream,bits/stdc++.h等头文件会导致g++编译变慢 3 #include <cstdio> 4 using namespace std; 5 const int maxn=100001; 6 7 int n; 8 int len[maxn]; 9 int sh[maxn]; 10 void modify(int p,int v) { len[p]+=v; for (int i=p;i<=n;i+=i&(-i)) sh[i]+=v; } 11 int sum(int p) 12 { 13 int ret=0; 14 for (int i=p;i;i-=i&(-i)) ret+=sh[i]; 15 return ret; 16 } 17 int main() 18 { 19 int q; 20 scanf("%d%d",&n,&q); 21 for (int i=1;i<=n;i++) modify(i,1); 22 for (int d,l=1,r=n,flag=0,p,a,b;q--;) 23 { 24 scanf("%d",&d); 25 if (d==1) 26 { 27 scanf("%d",&p); 28 int gs=r-l+1; 29 //if (flag) p=gs-p;//-- 30 /*int mid=(l+r>>1)-l+1;//-- 31 if (mid<=p)// 32 { 33 p=gs-p; 34 flag=!flag; 35 }*/ 36 if (gs<p*2) 37 { 38 p=gs-p; 39 flag=!flag; 40 } 41 if (!flag) 42 { 43 l+=p; 44 for (int i=1;i<=p;i++) modify(l+i-1,len[l-i]); 45 } 46 else 47 { 48 r-=p; 49 for (int i=1;i<=p;i++) modify(r-i+1,len[r+i]); 50 } 51 //cout<<sum(r)-sum(l-1)<<endl; 52 //printf("%d %d %d ",l,r,flag); 53 } 54 else 55 { 56 scanf("%d%d",&a,&b); 57 printf("%d ",!flag?sum(b+l-1)-sum(a+l-1):sum(r-a)-sum(r-b)); 58 } 59 } 60 }
Codeforces Round #265 Div.1:
C. Substitutes in Number
这是道智商题。从后往前做就能出解。要注意的是最后的size会超long long, 有可能会达到10^10000这种级别。所以要用到费马小定理的知识。
不过...我把这道智商题转换成了模拟题...
1 //7717006 2014-09-08 05:05:19 moxiaomo C - Substitutes in Number GNU C++ Accepted 108 ms 20500 KB 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <iostream> 6 #define pb push_back 7 #define mp make_pair 8 #define fir first 9 #define sec second 10 using namespace std; 11 typedef long long LL; 12 const int maxn=100001; 13 const LL MOD=1000000007; 14 //LL mi[maxn]; 15 16 int pos,ta[10],lin[maxn*2],sd[maxn*2],ssd[maxn*2]; 17 void biu(int s,int t,int tt) { ++pos; lin[pos]=ta[s]; ta[s]=pos; sd[pos]=t; ssd[pos]=tt; } 18 19 LL ksm(LL a,LL n,LL p) 20 { 21 LL ret=1; 22 for (a%=p;n;n>>=1) 23 { 24 if (n&1) ret=ret*a%p; 25 a=a*a%p; 26 } 27 return ret; 28 } 29 30 int q; 31 char s[maxn],ss[maxn]; 32 33 vector< pair<char,int> > bye[maxn]; 34 /*bool vis[maxn]; 35 int jl[maxn],po; 36 void cl(int v,char c,int f) 37 { 38 if (vis[v]) return; 39 vis[v]=1; jl[++po]=v; 40 for (int i=0;i<bye[v].size();i++) 41 if (bye[v][i].sec) cl(bye[v][i].sec,c,f); 42 else if (bye[v][i].fir==c) bye[v][i].sec=f; 43 }*/ 44 45 LL f[maxn],size[maxn]; 46 pair<LL,LL> solve(int v) 47 { 48 if (f[v]!=-1) return mp(f[v],size[v]); 49 f[v]=0; 50 pair<LL,LL> tp; 51 for (int i=bye[v].size()-1;~i;i--) 52 { 53 if (bye[v][i].sec) 54 { 55 tp=solve(bye[v][i].sec); 56 f[v]=(f[v]+tp.fir*ksm(10ll,size[v],MOD))%MOD; 57 size[v]=(size[v]+tp.sec); 58 } 59 else 60 f[v]=(f[v]+(bye[v][i].fir-'0')*ksm(10ll,size[v],MOD))%MOD, 61 size[v]=(size[v]+1); 62 } 63 return mp(f[v],size[v]%=(MOD-1)); 64 } 65 int main() 66 { 67 scanf("%s%d",s,&q); 68 for (int i=0;s[i];i++) 69 biu(s[i]-'0',0,i), 70 bye[0].pb(mp(s[i],0)); 71 for (int i=0;i<=q;i++) f[i]=-1; 72 73 for (int len,tt=1;tt<=q;tt++) 74 { 75 scanf("%s",ss); 76 len=strlen(ss); 77 78 for (int i=ta[ss[0]-'0'];i;i=lin[i]) 79 bye[sd[i]][ssd[i]].sec=tt; 80 ta[ss[0]-'0']=0; 81 82 for (int i=3;i<len;i++) 83 biu(ss[i]-'0',tt,i-3), 84 bye[tt].pb(mp(ss[i],0)); 85 /*cl(0,ss[0],tt); 86 while (po) vis[jl[po--]]=0;*/ 87 } 88 cout<<solve(0).fir<<endl;//printf("%I64d ",solve(0).fir); 89 return 0; 90 } 91 92 /*for (int i=bye[v].size()-1;~i;i--) 93 if (bye[v][i].sec) solve(bye[v][i].sec); 94 else 95 size[v]+=1, 96 ans=(ans+(bye[v][i].fir-'0')*tp)%MOD, 97 tp=tp*10%MOD;*/ 98 /*LL tp=1; 99 for (int i=strlen(s)-1;~i;i--) 100 { 101 ans[s[i]-'0']=(ans[s[i]-'0']+tp)%MOD; 102 tp=tp*10%MOD; 103 }*/