2018年icpc瀋陽賽區C題

簡單的計數題,題意是讓你對一個1到n的一個排列執行k次插入排序,排完序以後要滿足最長上升遞增子序列的長度至少爲n-1,問這樣的排列由多少種。做的時候是這樣做的,首先考慮前k個正好是前k個,然後後面的最長上升子序列大於等於n-k-1的排列的個數有多少,剛開始手推,發現推出來的公式是錯誤的,然後這個就打了一下表,之後考慮前面的k個有一個不屬於1到k的範圍以內,在紙上畫了一下,發現第k個值比較特殊,多了n-k-1種,其他的都是一樣就把第k+1個值插入放到前面,然後前面這個數插入到後面的空位中就行了。

代碼:

#include<bits/stdc++.h>
using namespace std;
int data[1000] = {1, 1, 2, 5, 10, 17, 26, 37, 50, 65, 82, 101, 122, 145, 170,
                  197, 226, 257, 290, 325, 362, 401, 442, 485, 530, 577, 626, 677, 730, 785, 842,
                  901, 962, 1025, 1090, 1157, 1226, 1297, 1370, 1445, 1522, 1601,
                  1682, 1765, 1850, 1937, 2026, 2117, 2210, 2305, 2402, 2501,
                 };
using ll=long long ;
int main()
{
    int t;
    while(scanf("%d",&t)!=EOF)
    {
        int x=1;
        ll n,k,q;
        while(t--)
        {
            scanf("%lld%lld%lld",&n,&k,&q);
            k=min(n,k);
            if(k==1)
            {
                printf("Case #%d: %I64d\n",x++,data[n]%q);
            }
            else  if(k==n)
            {
                ll ans=1;
                for(ll i=1; i<=n; i++)
                    ans=ans*i%q;
                printf("Case #%d: %I64d\n",x++,ans);
            }
            else
            {
                ll ans=1;
                for(int i=1; i<=k; i++)
                {
                    ans=ans*i%q;
                }
                ans = ans*(data[n-k] + k*(n-k)+n-k-1)%q;
                printf("Case #%d: %I64d\n",x++,ans);

            }
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章