lucky tickets

brute force:

#include<iostream> using namespace std; int ans,curCnt; int curNumber; int cnt; void work(int k,int cur){//k<=cnt-1,cur<=curNumber if(k==cnt-1){ if(curNumber>=cur&&curNumber<=cur+9)curCnt++;// ÕâÒ»¾äshit!!! } else{ if(cur+(cnt-k)*9<curNumber)return; int i; for(i=0;i<10;i++){ if(cur+i>curNumber)return; work(k+1,cur+i); } } } int main(){ int n; cin>>n; if(n&1){ cout<<0<<endl; return 0; } ans=2; int i; cnt=n/2; for(i=1;i<cnt*9;i++){ curNumber=i; curCnt=0;//0,max work(0,0); ans+=(curCnt*curCnt); } cout<<ans<<endl; return 0; }

dp[n][s]为n个数字和为s的方案数
则转移方程:dp[n+1][s+i]+=dp[n][s]   -1<i<10
代码:
#include<iostream> using namespace std; int main(){ int n; cin>>n; if(n&1){ cout<<0<<endl; return 0; } int i,j,k; int dp[6][9*5+1]; int max=9; memset(dp,0,sizeof(dp)); fill(dp[1],dp[1]+10,1); for(i=1;i<n/2;i++){ for(j=0;j<=max;j++){ for(k=0;k<=9;k++){ dp[i+1][j+k]+=dp[i][j]; } } max+=9; } int ans=0; for(j=0;j<=max;j++){ ans+=(dp[i][j]*dp[i][j]); } cout<<ans<<endl; return 0; }

结果悲剧了
brute force:oMS
dp:16MS!
  最初是打算看递归的结果看了放开递推思想(ACM_DIY中的鱼神所写),注意是放开,就是别一直想着用它,弄巧成拙学了容斥原理。
例题用的就是ural1036(Lucky Tickets),poj2346只是它的一个缩减的版本。 
lucky tickets_第1张图片
lucky tickets_第2张图片
代码:
  #include<iostream> using namespace std; int cnt[6]; __int64 c(__int64 n,__int64 m){ if(n==0)return 1; __int64 mul=1; for(int i=1;i<=m;i++,n--)mul=mul*n/i; return mul; } int main(){ fill(cnt,cnt+6,2);//0,max int n; while(cin>>n){ if(n&1)cout<<0; else{ n/=2; if(cnt[n]>2)cout<<cnt[n]; else{ int s,i; for(s=1;s<n*9;s++){ __int64 sum=0; for(i=0;i<=n;i++){ if(s<10*i)break; __int64 t=c(n,i)*c(s-10*i+n-1,s-10*i); if(i&1)t=-t; sum+=t; } cnt[n]+=sum*sum; } cout<<cnt[n]; } } cout<<endl; } return 0; }

你可能感兴趣的:(lucky tickets)