20140708总结

今天的题还是比较水的。。涨自信?

第一题。。显而易见的dp:dp[i][j][k][l][m]:表示i位,j个1,k是否顶上界,l个前导零,是否仍在前导零上。转移方程比较复杂,详见代码。

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 using namespace std;

 5 long long dp[50][50][2][50][2];

 6 long long work(long long x)

 7 {

 8     long long top[200];

 9     memset(dp,0,sizeof(dp));

10     memset(top,0,sizeof(top));

11     long long i=1;

12     long long j=1;

13     if(x==0) return 0;

14     while(x/j)

15     {

16         i++;

17         j*=2;

18     }

19     if(i)

20         i--;

21     long long n=i;

22     while(x)

23     {

24         top[i]=x%2;

25         x/=2;

26         i--;

27     }

28 //    for(int i=1;i<=n;i++)

29 //        cout<<top[i];

30 //    cout<<endl<<endl;

31     dp[1][0][1][0][0]=1;

32 //    for(int i=1;i<=n;i++)

33 //        cout<<top[i];

34 //    cout<<endl;

35     for(i=1;i<=n;i++)

36         for(j=0;j<=n/2;j++)

37             for(int k=0;k<=n;k++)

38             {

39                 dp[i+1][j][0][k+1][0]+=dp[i][j][0][k][0];

40                 dp[i+1][j+1][0][k][1]+=dp[i][j][0][k][0];

41                 if(top[i]==0)

42                     dp[i+1][j][1][k+1][0]+=dp[i][j][1][k][0];

43                 else

44                 {

45                     dp[i+1][j][0][k+1][0]+=dp[i][j][1][k][0];

46                     dp[i+1][j+1][1][k][1]+=dp[i][j][1][k][0];

47                 }

48                 for(long long l=0;l<=1;l++)

49                     dp[i+1][j+l][0][k][1]+=dp[i][j][0][k][1];

50                 for(long long l=0;l<=top[i];l++)

51                     dp[i+1][j+l][l==top[i]][k][1]+=dp[i][j][1][k][1];

52 //                cout<<dp[i][j][up]<<endl;

53             }

54     long long ans=0;

55     for(int k=0;k<=n;k++)

56         for(int i=1;i<=(n-k)/2;i++)

57         {

58             ans+=dp[n+1][i][0][k][1]+dp[n+1][i][1][k][1];

59         }

60     

61 //    for(int j=1;j<=n+1;j++)

62 //    for(int k=0;k<=n;k++)

63 //    for(int i=1;i<=n;i++)

64 //        cout<<dp[j][i][0][k][1];

65     return ans;

66 }

67 void work()

68 {

69     freopen("testA.in","r",stdin);

70     freopen("testA.out","w",stdout);

71     long long L,R;

72     cin>>L>>R;

73     if(L==1)

74         cout<<work(R)<<endl;

75     else

76         cout<<work(R)-work(L-1)<<endl;

77 //    cout<<work(R)<<"  "<<work(L-1)<<endl;

78 }

79 int main()

80 {

81     work();

82     return 0;

83 }
View Code

 第二题比较复杂,大意就是把[ai,bi] 作为区间,落在[1,N]上,互不重叠,长度互不相等。然后dp[j][k]表示在i位,选了k个,其和为j。

然后答案就是20140708总结,详见标程代码(我还没有写出来)。

 

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<string>

 5 using namespace std;

 6 const long long MOD =1000000007LL;

 7 long long dp[1007][1007];

 8 long long C[2014][2014];

 9 long long x[101];

10 #ifdef unix

11 #define LL "%lld\n"

12 #else 

13 #define LL "I64d\n"

14 #endif

15 void init()

16 {

17     memset(dp,0,sizeof(dp));

18     memset(C,0,sizeof(C));

19     memset(x,0,sizeof(x));

20     x[0]=1;

21     for(int i=1;i<=100;i++)

22         x[i]=x[i-1]*i%MOD;

23     for(int i=1;i<1000;i++)

24     {

25         C[i][i]=1;

26         C[i][0]=1;

27         for(int j=1;j<i;j++)

28         {

29             C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;

30         }

31     }

32     dp[0][0]=1;

33     for(int i=1;i<=1000;i++)    

34         for(int j=1000;j>=i;j--)

35             for(int k=50;k>0;k--)

36                 dp[k][j]=(dp[k][j]+dp[k-1][j-i])%MOD;

37 }

38 int main()

39 {

40     init();

41     int T,N,K;

42     cin>>T;

43     long long ans=0;

44     while(T--)

45     {

46         cin>>N>>K;

47         if(K*(K+1)/2>N)

48         {

49             printf("0\n");

50             continue;

51         }

52         ans=0;

53         for(int L=K;L<=N;L++)

54         {

55             ans=(ans+dp[K][L]*C[N+K-L][K]%MOD)%MOD;

56         }

57         printf("%lld\n",(ans*x[K])%MOD);

58     }

59 }
View Code

 

第三题比较水,我就不多说什么了,多特判就好了。。

 1 #include<iostream>

 2 #include<cstdio>

 3 using namespace std;

 4 int main()

 5 {

 6     freopen("testC.in","r",stdin);

 7     freopen("testC.out","w",stdout);

 8     int n,m,x;

 9     cin>>n>>m>>x;

10     if(x<0)

11     {

12         cout<<0<<endl;

13         return 0;

14     }

15     if(x==0)

16     {

17         cout<<n*m/2<<endl;

18         return 0;

19     }

20     x-=1;

21     n-=2*x;

22     m-=2*x;

23     if(n<=0||m<=0)

24         cout<<0<<endl;

25     else if(n==1||m==1)

26         cout<<n*m-n*m/2<<endl;

27     else

28         cout<<(n+m)-2<<endl;

29     return 0;

30 }
View Code

 

 

你可能感兴趣的:(总结)