Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3247 | Accepted: 2136 |
Description
So you are to save public transport of our city. Write a program that determines a number of lucky tickets for the given number of digits. By the way, there can't be more than 10 digits on one ticket.
Input
Output
Sample Input
4
Sample Output
670
題意是要找幸運數字,所謂幸運數字就是一個n位(n爲偶數)的數字,前n/2位每位的數字和與後n/2位的數字和相等。
因爲這題第一位0也包括進去了,題目難度減少好多。
然後一看n最大才10,難度一下子下降更多了。就不管dp了,直接打表暴力。
幸好是最大是10,電腦跑了一會纔有結果。要是12估計電腦都會跑好久。
暴力代碼(n爲10時):
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
int i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,result=0;
for(i1=0;i1<=9;i1++)
for(i2=0;i2<=9;i2++)
for(i3=0;i3<=9;i3++)
for(i4=0;i4<=9;i4++)
for(i5=0;i5<=9;i5++)
for(i6=0;i6<=9;i6++)
for(i7=0;i7<=9;i7++)
for(i8=0;i8<=9;i8++)
for(i9=0;i9<=9;i9++)
for(i10=0;i10<=9;i10++)
if(i1+i2+i3+i4+i5==i6+i7+i8+i9+i10)
result++;
cout<<result<<endl;
system("pause");
return 0;
}
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
int result[12],n;
result[0]=0;
result[2]=10;
result[4]=670;
result[6]=55252;
result[8]=4816030;
result[10]=432457640;
cin>>n;
cout<<result[n]<<endl;
return 0;
}
這麼一看這道題還真是水啊。。。
以上是我2015年7月11日時犯下的二逼想法,等到我10月份做到51nod1043的幸運數字時,想起了2346discuss上面的一個dp,於是就順着那個思路去想了。然後就一直wa。
才發現其實這個dp很簡單,遠遠沒有我之前想得那麼麻煩。
用dp[i][j]表示i個數的和爲j的總數,這裏面是包括0開頭的情形,有dp[i][j]=dp[i-1][j-k](k從0到9)。很好想,i個數組成總和爲j的數量就來自於i-1個數 裏面能 在最前面加0到9的數字使得加完之後和爲j。
這裏麪包含了0開頭的,把0去掉的方法就是dp[i][j]-dp[i-1][j]。dp[i-1][j]就代表了在i個數中,開頭爲0的個數,減去就是i個數中開頭不爲0的個數。原因很明顯,i個數和爲j與i-1個數和爲j,就差了一個位置爲0。而這一個位置因爲一開始咱們的想法就是在最前面加的數字,所以這個位置就差在了最前面的位置上。
所以根據51nod 又把poj2346的代碼改了一下,就是
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std;
#define maxn 1005
const int mod = 1000000007;
long long dp[2][9*maxn];
int n;
int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);
int i,j,k;
long long ans;
cin>>n;
n=n/2;
memset(dp,0,sizeof(dp));
//dp[0][1]=1;//此處單獨爲了1 考慮
for(i = 0; i <= 9; ++ i)
{
dp[1][i] = 1;
}
for(i=2;i<=n;i++)
{
for(k=0;k<=n*9;k++)
{
long long sum=0;
for(j=0;j<=9;j++)
{
if(k>=j)
sum = (sum+dp[(i-1)&1][k-j])%mod;
else
dp[i&1][k]=0;
}
dp[i&1][k]=sum;
}
}
ans=0;
for(i=0;i<=n*9;i++)
{
ans = (ans+dp[n&1][i]*(dp[n&1][i]))%mod;
}
cout<<ans<<endl;
//system("pause");
return 0;
}
當然,題目沒有要求mod 1e9+7。
然後是51nod1043 幸運號碼:
輸入N(1<= N <= 1000)
輸出幸運號碼的數量 Mod 10^9 + 7
1
9
代碼:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std;
#define maxn 1005
const int mod = 1000000007;
long long dp[2][9*maxn];
int n;
int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);
int i,j,k;
long long ans;
cin>>n;
memset(dp,0,sizeof(dp));
dp[0][1]=1;//此處單獨爲了1 考慮
for(i = 0; i <= 9; ++ i)
{
dp[1][i] = 1;
}
for(i=2;i<=n;i++)
{
for(k=0;k<=n*9;k++)
{
long long sum=0;
for(j=0;j<=9;j++)
{
if(k>=j)
sum = (sum+dp[(i-1)&1][k-j])%mod;
else
dp[i&1][k]=0;
}
dp[i&1][k]=sum;
}
}
ans=0;
for(i=0;i<=n*9;i++)
{
ans = (ans+dp[n&1][i]*(dp[n&1][i]-dp[(n-1)&1][i]))%mod;
}
cout<<ans<<endl;
//system("pause");
return 0;
}
發現就是不斷看自己寫過的筆記,也在發現自己得到的成長。三個月的時間,和之前的很多想法都不太一樣了。