zoukankan      html  css  js  c++  java
  • Test on 11/4/2018

    来浙理的第一次月赛,嗯我是被大佬吊着打的垃圾。

    A:优美数

    Description

    如果一个数中只有少于三个数字是非零的,那么我们称这个数为优美数,我们定义这个优美数的优美程度为这个数所有数字相加的和。 例如优美数有4,200000,10203,其中4的优美度是4,200000的优美度是2,10203的优美度是6. 数字4231,102306,7277420000,就不是啰。

    现在问在【L,R】中,有多少个优美度为x的优美数。

    Input

    T组数据,T<=5e4. 第一行为组数T。 接下来T行,每组输入L,R,x。1<=L <= R <= 3e18;

    Output

    每行输出一个对应的答案

    Examples

    Input

    4

    1 1000 1

    1024 1024 7

    65536 65536 15

    1 1000000000 20

    Output

    4

    1

    0

    3024

     

    正确解法:

    先dfs,预处理所有的情况,然后对每次询问进行二分求解。

    也可用数位DP。

      1 #include <algorithm>
      2 #include  <iterator>
      3 #include  <iostream>
      4 #include   <cstring>
      5 #include   <cstdlib>
      6 #include   <iomanip>
      7 #include    <bitset>
      8 #include    <cctype>
      9 #include    <cstdio>
     10 #include    <string>
     11 #include    <vector>
     12 #include     <stack>
     13 #include     <cmath>
     14 #include     <queue>
     15 #include      <list>
     16 #include       <map>
     17 #include       <set>
     18 #include   <cassert>
     19 using namespace std;
     20  
     21  
     22 typedef long long ll;
     23  
     24             const int maxn = 3e6+9;
     25             int tot = 0;
     26             vector<ll>mp[30];
     27             int cnt(ll x){
     28                 int res = 0;
     29                 while(x>0){
     30                     res += x%10;
     31                     x/=10;
     32                 }
     33                 return res;
     34             }
     35             set<int>sss;
     36             void dfs(ll x,int cur,int num){
     37                 if(cur>19||num > 3)return;
     38  
     39                 if(num<=3){
     40                     int tmp = cnt(x);
     41                     mp[tmp].pb(x);
     42                     // tot++;
     43                     sss.insert(tmp);
     44                     // if(cnt(x) == 50)cout<<x<<endl;
     45                 }
     46                 for(int i=0;i<=9; i++){
     47                     if(i==0)dfs(x*10ll, cur+1,num);
     48                     else dfs(x*10ll + i, cur+1,num+1);
     49                 }
     50             }
     51             int find1(ll x,int id){
     52                 int le = 0,ri = mp[id].size() - 1;
     53                 int res = ri+1;
     54                 while(le <= ri){
     55                     int mid = (le + ri)>>1;
     56                     
     57                     if(mp[id][mid] < x){
     58                         le = mid+1;
     59                     }
     60                     else{
     61                         res = mid; ri = mid - 1;
     62                     }
     63                 }
     64  
     65                 return res;
     66             }
     67              int find2(ll x,int id){
     68                 int le = 0,ri = mp[id].size() - 1;
     69                 int res = 0;
     70                 while(le <= ri){
     71                     int mid = (le + ri)>>1;
     72                     if(mp[id][mid] > x){
     73                         ri = mid - 1;
     74                     }
     75                     else {
     76                         res = mid;
     77                         le = mid + 1;
     78                     }
     79                 }
     80                 return res;
     81             }
     82 int main(){
     83  
     84             // freopen("data.in","r", stdin);
     85             // freopen("output.out","w",stdout);
     86             for(int i=1; i<=9; i++)dfs(i,1,1);
     87             //tot = 720423
     88     
     89             for(int k : sss){//27次
     90                 sort(mp[k].begin(),mp[k].end());
     91             }
     92  
     93             int t;scanf("%d", &t);
     94             while(t--){
     95                 ll l,r;int x;
     96                 scanf("%lld%lld%d", &l, &r, &x);
     97                 if(x >= 28){
     98                     puts("0");
     99                 }
    100                 else if(l<r){
    101                         int t1 = find1(l,x);
    102                         int t2 = find2(r,x);
    103                         printf("%d
    ",t2 - t1 + 1);
    104                 }
    105                 else if(l==r){
    106                         int t1 = lower_bound(mp[x].begin(),mp[x].end(),l) - mp[x].begin();
    107                         if(t1<mp[x].size() && mp[x][t1] == l)puts("1");
    108                         else puts("0");
    109                 }
    110             }
    111            return 0;
    112 }
    View Code
     1 #include <algorithm>
     2 #include  <iterator>
     3 #include  <iostream>
     4 #include   <cstring>
     5 #include   <cstdlib>
     6 #include   <iomanip>
     7 #include    <bitset>
     8 #include    <cctype>
     9 #include    <cstdio>
    10 #include    <string>
    11 #include    <vector>
    12 #include     <stack>
    13 #include     <cmath>
    14 #include     <queue>
    15 #include      <list>
    16 #include       <map>
    17 #include       <set>
    18 #include   <cassert>
    19 using namespace std;
    20 #define se second
    21 #define fi first
    22 #define ll long long
    23 #define Pii pair<int,int>
    24 #define Pli pair<ll,int>
    25 #define ull unsigned long long
    26 #define pb push_back
    27 const int N=1e4+10;
    28 const int INF=0x3f3f3f3f;
    29 const int mod=1e9+7;
    30 using namespace std;
    31 int a[30];
    32 ll dp[20][30][4][30];
    33 int k;
    34 ll dfs(int pos,int now,int num,bool limit){
    35     if(num > 3) return 0;
    36     if(pos==-1) return now == k;
    37     if(!limit && dp[pos][now][num][k]!=-1) return dp[pos][now][num][k];
    38     int up=limit?a[pos]:9;
    39     ll ans=0;
    40     for(int i=0;i<=up&&now+i<=k;++i){
    41        ans+=dfs(pos-1,now+i,num+(i!=0),limit&&i==a[pos]);
    42     }
    43     if(!limit) dp[pos][now][num][k]=ans;
    44     return ans;
    45 }
    46 ll solve(ll x){
    47     int pos=0;
    48     if(x==0)return 0;
    49     while(x){
    50         a[pos++]=x%10;
    51         x/=10;
    52     }
    53     return dfs(pos-1,0,0,1);
    54 }
    55 int main(){
    56 //    freopen("data1.in", "r", stdin);
    57 //    freopen("ac.out", "w", stdout);
    58     memset(dp,-1,sizeof(dp));
    59  
    60     int T;scanf("%d",&T);
    61     while(T--){
    62         ll l,r;
    63         scanf("%I64d%I64d%d",&l,&r,&k);
    64         if(k>27)printf("0
    ");
    65         else printf("%I64d
    ",solve(r)-solve(l-1));
    66     }
    67  
    68     return 0;
    69 }
    View Code

    B:私人奶茶店

    Description

    C有一家奶茶店,其中有n种奶茶,每种奶茶都有a【i】个,小C每天都会等概率地从剩余的奶茶中选一杯奶茶喝掉,问小C第K天喝到第m种奶茶的概率是多少。

    Input

    第一行n,代表奶茶的种类数

    第二行n个数,表示a【i】

    第三行k,m,表示第k天喝到第m种奶茶的概率

    n<=1e5, 0 < a[i] <= 1e6

    1<=k<=sum(a[i]), 1<=m<=n)

    Output

    用最简分数表示。

    Examples

    Input

    2

    1 1

    1 1

    Output

    1/2

    正确解法:

    a[m] / sum   与k无关,最后要gcd

     1 #include <cstdio>
     2 #include <iostream>
     3 using namespace std;
     4 typedef long long ll;
     5 const int maxn = 1e5+9;
     6 ll a[maxn];
     7 ll gcd(ll a, ll b){
     8     if(b==0)return a;
     9     return gcd(b, a%b);
    10 }
    11 int main(){ 
    12         // freopen("data5.in", "r", stdin);
    13         int n;scanf("%d", &n);
    14         ll sum = 0;
    15         for(int i=1; i<=n; i++)scanf("%lld", &a[i]),sum+=a[i];
    16         cout<<"sum"<<sum<<endl;
    17         int k,m;
    18         scanf("%d%d", &k, &m);
    19         ll g = gcd(sum,a[m]);
    20         printf("%lld/%lld
    ", 1ll*a[m]/g, 1ll*sum/g);
    21         return 0;
    22 }
    View Code

    C:素数空间

    Description

    一天,小明正在搬砖,他收集了n(n<=1e7)种砖,砖的编号1-n这个时候,他突然说了一句,召唤神龙,然后,他穿越到了一个时空,发现这里的东西都是由素数组成的,这里的砖也和素数有关,他的砖也和他一块过来了,只是发生了一些变化,编号为1的砖不见了,编号为素数的砖没有发生变化,编号为合数的砖变成了编号为几块素数的砖(砖的编号和为之前的那个合数),由于这个世界能量太少,所以这些合数的砖尽可能的变成数目少的其他砖。于是小明想请教你他还有多少砖。例如 编号为12的砖会变成编号5 7 的砖  不会变成编号2 3 2 2 3 的砖     编号9的砖会变成编号2 7 的砖  不会变成编号 3 3 3  的砖

    Input

    给你一个T(1<=T<=3e3) 
    接下来T行每行一个n(0<=n<=1e7)

    Output

    一共T行,每一行输出一个结果;

    Examples

    Input

    2

    3

    5

    Output

    2

    5

    正确解法:

    根据哥德巴赫猜想

    大于二的偶数可以分解为两个素数之和

    大于七的奇数可以分解为三个素数之和

    (一定可以分解成三个素数之和,也有可能分解为两个,分解成两个其中必然有一个是2,其他就是至少三个)

    1.先线性筛出所有的素数。

    2.遍历1-le7里的素数、偶合数、奇合数

    3.预处理一遍就行了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e7+5;
     4 bool prime[maxn];
     5 int p[maxn];
     6 int tot;
     7 void findprime()
     8 {
     9     for(int i = 2; i < maxn; i ++)  prime[i] = true;
    10     for(int i = 2; i < maxn; i ++)
    11     {
    12         if(prime[i])  p[++tot]=i;
    13         for(int j=1;j<=tot && i*p[j]<maxn; j++)
    14         {
    15             prime[i*p[j]]=false;
    16             if(i%p[j]== 0) break;
    17         }
    18     }
    19 }
    20 int  ans[maxn];
    21 int main()
    22 {
    23    // freopen("g4.in","r",stdin);
    24    // freopen("g4.out","w",stdout);
    25     findprime();
    26     for(int i=2;i<=maxn;i++)
    27     {
    28         if(prime[i]==1) ans[i]=ans[i-1]+1;
    29         else
    30         {
    31             if(i%2==0) ans[i]=ans[i-1]+2;
    32             else
    33             {
    34                 if(prime[i-2]==1) ans[i]=ans[i-1]+2;
    35                 else              ans[i]=ans[i-1]+3;
    36             }
    37         }
    38     }
    39    int t;cin>>t;
    40    while(t--)
    41    {
    42        int n; cin>>n; cout<<ans[n]<<endl;
    43    }
    44 }
    View Code

    D:摩天大楼

    Description

    随着科技的发展,某国家准备修建一座高楼,高度为n(n<=1e18),来展现他们国家的强大国力,他们国家有两支强大的施工队,国家于是把修建计划给了这两只施工队,为了提高施工队的积极性,国家会特殊奖励最后完成施工的,两只施工的施工计划是两只施工队轮流工作,由于施工队实力有限,每天只能修建1-m(m<=1e18)层,假如两只施工队都非常聪明,问首先施工的那只队伍能不能获得奖励,能输出YES,不能输出NO

    Input

    数据的组数 T;(T<=3000)     

    接下来T行,每行一个n m, 楼的高度,最大修建层数   (n,m<=1e18)

    Output

    每行一个单独的YES或者NO;

    Examples

    Input

    2

    2 1

    6 4

    Output

    NO

    YES

    正确解法:

    两只队伍都非常聪明,知道如何使自己赢,每个人取的都是1~m个

    无论第一支队伍取多少个,第二支队伍都能使两只队伍的和为1+m 个

    故 n为m+1的倍数或者0时候,先手必输,其余先手必赢.

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int main()
     4 {
     5    // freopen("cc.in","r",stdin);
     6   //  freopen("in.out","w",stdout);
     7     long long n,m;
     8     int t; cin>>t;
     9     while(t--)
    10     {
    11        cin>>n>>m;
    12       if(n%(m+1)==0) cout<<"NO"<<endl;
    13        else           cout<<"YES"<<endl;
    14     }
    15 }
    View Code

    E:招生

    Description

     浙江理工大学招生,一开始有0名学生报考,现在有如下几种情况;

    1.增加一名报考学生,报考学生成绩为x;

    2.一名成绩为x的学生放弃报考。

    3.从现在报考的学生来看,老师想知道如果要招生至少x名学生,需要将分数线最高设置为多少;

    4.从现在报考的学生来看,如果分数线设置为x,能有几名学生被录取。

    第一行先输入一个n,表示有n次操作或查询;

    接下来n行,每行输入两个整数opt和x(用空格隔开):

    如果opt为1,则增加一名报考学生,报考学生成绩为x;

    如果opt为2,则表示一名成绩为x的学生放弃报考。

    如果opt为3,从现在报考的学生来看,老师想知道如果要招生至少x名学生,需要将分数线最高设置为多少,输出最高分数线。

    如果opt为4,从现在报考的学生来看,如果分数线设置为x,能有几名学生被录取,输出录取人数。

    对于每个输出占一行。

    n不超过50000;0<=x<=1000000;1<=k<=现在的学生数。

    Input

    第一行输入一个n,接下来n行,每行输出两个整数opt,x,用空格隔开

    Output

    对于每次输出, 输出一个整数占一行

    Examples

    Input

    18

    1 3

    1 4

    1 5

    1 6

    1 7

    1 8

    1 9

    1 10

    1 11

    1 12

    2 8

    3 2

    3 3

    3 4

    3 5

    4 8

    4 9

    4 7

    Output

    11

    10

    9

    7

    4

    4

    5

    正确解法:

    平衡树treap

      1 #include<bits/stdc++.h>
      2 #define fi first
      3 #define se second
      4 #define INF 0x3f3f3f3f
      5 #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
      6 #define pqueue priority_queue
      7 #define NEW(a,b) memset(a,b,sizeof(a))
      8 const double pi=4.0*atan(1.0);
      9 const double e=exp(1.0);
     10 const int maxn=1e6+8;
     11 typedef long long LL;
     12 typedef unsigned long long ULL;
     13 //typedef pair<LL,LL> P;
     14 const LL mod=1e9+7;
     15 const ULL base=1e7+7;
     16 using namespace std;
     17 struct node{
     18     int son[2];
     19     int siz;
     20     int key,w;
     21 }a[maxn];
     22 int tot=0;
     23 int root=0,vis[maxn];
     24 void up(int i){
     25     a[i].siz=a[a[i].son[0]].siz+a[a[i].son[1]].siz+1;
     26 }
     27 void Rotate(int &i,int d){
     28     int t=a[i].son[d];
     29     a[i].son[d]=a[t].son[!d];
     30     a[t].son[!d]=i;
     31     up(i);up(t);
     32     i=t;
     33 }
     34 void Insert(int &i,int key){
     35     if(i==0){
     36         i=++tot;
     37         a[i].siz=1;a[i].key=key;a[i].w=rand();
     38         return ;
     39     }
     40     a[i].siz++;
     41     if(a[i].key>=key) {
     42         Insert(a[i].son[0],key);
     43         if(a[a[i].son[0]].w<a[i].w) Rotate(i,0);
     44     }
     45     else{
     46         Insert(a[i].son[1],key);
     47         if(a[a[i].son[1]].w<a[i].w) Rotate(i,1);
     48     }
     49 }
     50 void Del(int &i,int key){
     51     if(a[i].key==key){
     52         if(a[i].son[0]*a[i].son[1]==0)  {i=a[i].son[0]+a[i].son[1];return ;}
     53         if(a[a[i].son[0]].w>a[a[i].son[1]].w){
     54             Rotate(i,1);
     55             Del(a[i].son[0],key);
     56         }
     57         else{
     58             Rotate(i,0);
     59             Del(a[i].son[1],key);
     60         }
     61     }
     62     else if(a[i].key>key){
     63         Del(a[i].son[0],key);
     64     }
     65     else{
     66         Del(a[i].son[1],key);
     67     }
     68     up(i);
     69 }
     70 int Find(int i,int key){
     71     if(i==0) return 1;
     72     if(a[i].key>=key) return Find(a[i].son[0],key);
     73     else return a[a[i].son[0]].siz+Find(a[i].son[1],key)+1;
     74 }
     75 int Search(int i,int rak){
     76     if(a[a[i].son[0]].siz==rak-1) return a[i].key;
     77     if(a[a[i].son[0]].siz>=rak) return Search(a[i].son[0],rak);
     78     else  return Search(a[i].son[1],rak-a[a[i].son[0]].siz-1);
     79 }
     80 int pre(int i,int key){
     81     if(i==0) return -10000008;
     82     if(a[i].key<key) return max(a[i].key,pre(a[i].son[1],key));
     83     return pre(a[i].son[0],key);
     84 }
     85 int bhe(int i,int key){
     86     if(i==0) return 10000008;
     87     if(a[i].key>key) return min(a[i].key,bhe(a[i].son[0],key));
     88     return bhe(a[i].son[1],key);
     89 }
     90 int main(){
     91     int n;
     92     freopen("data1.in","r",stdin);
     93     freopen("data1.out","w",stdout);
     94     scanf("%d",&n);
     95     int opt,x;
     96     int sum=0;
     97     while(n--){
     98         scanf("%d%d",&opt,&x);
     99         if(opt==1){
    100             Insert(root,x);
    101             sum++;
    102             vis[x]++;
    103         }
    104         if(opt==2){
    105             if(vis[x]){
    106                 Del(root,x);
    107                 sum--;
    108                 vis[x]--;
    109             }
    110         }
    111         if(opt==3){
    112             printf("%d
    ",Search(root,sum-x+1));
    113         }
    114         if(opt==4){
    115             printf("%d
    ",sum-Find(root,x)+1);
    116         }
    117     }
    118 }
    View Code

    F: 闲的无聊的简单题

    Description

    给你一个n*m的二维数组,a[i][j]表示第i行第j列的数字,现在求一个最大面积(长乘宽)的子矩形,要求对于该子矩形每一行中相邻的两个数,a[i][j]和a[i][j+1],存在一个整数k使得2的k次方同时小于等于a[i][j]和a[i][j+1],并且2的(k+1)次方大于a[i][j]和a[i][j+1],对于每一列中相邻的两个数,a[i][j]和a[i+1][j],不存在一个整数k使得2的k次方同时小于等于a[i][j]和a[i+1][j],并且2的(k+1)次方大于a[i][j]和a[i+1][j]。(0<n,m<=500)。

    Input

    第一行输入两个数n,m
    接下来n行,每行m个整数第i行第j列表示a[i][j](0<a[i][j]<=1e9)

    Output

    输出一个表示符合要求的最大矩形面积

    Examples

    Input

    4 4

    1 2 3 4

    5 6 7 8

    9 10 11 12

    13 14 15 16

    Output

    6

    描述:

    对于样例,面积为6的矩形如下
    2 3
    6 7
    10 11

    正确解法:

    判断一个数a与另一个数b是否存在一个k满足可以用异或,令c=a^b,如果c同时小于a和b,则存在,否则则不存在。开三个数组up,l,r存每个点上边,左边和右边可以到达的最值,并且l和r不断更新,每次不断更新面积最大值即可。
     
     1 #include<bits/stdc++.h>
     2 #define fi first
     3 #define se second
     4 #define INF 0x3f3f3f3f
     5 #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
     6 #define pqueue priority_queue
     7 #define NEW(a,b) memset(a,b,sizeof(a))
     8 const double pi=4.0*atan(1.0);
     9 const double e=exp(1.0);
    10 const int maxn=1e6+8;
    11 typedef long long LL;
    12 typedef unsigned long long ULL;
    13 const LL mod=1e9+7;
    14 const ULL base=1e7+7;
    15 using namespace std;
    16 int a[2008][2008];
    17 int l[2008][2008],r[2008][2008],u[2008][2008];
    18 int main(){
    19     //freopen("data5.in","r",stdin);
    20     //freopen("data5.out","w",stdout);
    21     int n,m;
    22     scanf("%d%d",&n,&m);
    23     for(int i=1;i<=n;i++){
    24         for(int j=1;j<=m;j++){
    25             scanf("%d",&a[i][j]);
    26         }
    27         l[i][1]=1;r[i][m]=m;
    28         int k;
    29         for(int j=2;j<=m;j++){
    30             k=a[i][j]^a[i][j-1];
    31             if(a[i][j]>=k&&a[i][j-1]>=k){
    32                 l[i][j]=l[i][j-1];
    33             }
    34             else{
    35                 l[i][j]=j;
    36             }
    37         }
    38         for(int j=m-1;j>=1;j--){
    39             k=a[i][j]^a[i][j+1];
    40             if(a[i][j]>=k&&a[i][j+1]>=k){
    41                 r[i][j]=r[i][j+1];
    42             }
    43             else{
    44                 r[i][j]=j;
    45             }
    46         }
    47     }
    48     int maxa=0;
    49     for(int i=1;i<=n;i++){
    50         for(int j=1;j<=m;j++){
    51             if(i>1&&(a[i][j]<(a[i][j]^a[i-1][j])||a[i-1][j]<(a[i][j]^a[i-1][j]))){
    52                 u[i][j]=u[i-1][j]+1;
    53                 l[i][j]=max(l[i][j],l[i-1][j]);
    54                 r[i][j]=min(r[i][j],r[i-1][j]);
    55             }
    56             else{
    57                 u[i][j]=1;
    58             }
    59             maxa=max(maxa,(r[i][j]-l[i][j]+1)*u[i][j]);
    60         }
    61     }
    62     //cout<<u[39][17]<<endl;
    63     cout<<maxa<<endl;
    64 }
    View Code

    G: 简单题*10086

    Description

    现有N个数c1,c2,...,cN。对于每个数求有多少个有序二元组(i,j)满足以下式子   

    ci * cj mod P=ck(i,j,k可想等)

    其中P为一给定质数。对于每个k对应的答案记为cnt[k],请你将每两个相邻的答案相加,这样答案总个数每次减少1,当答案个数为1时结束(结果对1e9+7取模)。为了感谢wjh、xxb、lmb、cly、ckx、yzj出了一堆简单题,请将他们名字缩写(小写)合并后去重并输出字典序第k大,k为所得结果乘上2333333后取模6666666的结果。

    Input

    第一行输入一个组数t(t ≤ 5)。
    对于每组数据第一行有两个正整数N,P(1 ≤ N ≤ 100000,2 ≤ P ≤ 100000), P为质数。
    第二行N个非负整数c1,c2,...,cN(0 ≤ ci ≤ 1e9)。

    Output

    输出共一行,为对应答案的字典序排列(答案为0输出-1)。

    Examples

    Input

    2

    7 3

    1 2 3 4 5 6 7

    5 7

    1 0 2 3 0

    Output

    ckybhmwzxjl

    byjlhwzmckx

    正确解法:

    例如答案是1 2 3 4 5那么你应该经过以下变化变成一个答案1 2 3 4 5 

    3 5 7 9
    8 12 16
    20 28
    48

     

    我们令g为质数P的原根,那么对于一个数字ai,唯一存在一个数字bi,使得  。那么我们把所有的ai用这种形式表示,于是对于原本的式子ci*cj≡ck(mod P),有,那么可以有bi+bj=bk。这样问题就从乘法变成了加法,FFT就可以排上用场了。而且你会发现,这里的bi的大小都是在P以内的。这样直接FFT即可,最后特殊处理一下0的情况即可。而对于接下来的一部可以发现最后结果就是C(n-1,0)*a[1]+C(n-1,1)*a[2]+……+C(n-1,n-1)*a[n],可以O(n)求出答案,最后一步是个逆康托展开。

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <bitset>
      5 #include <cmath>
      6 #include <cctype>
      7 #include <iostream>
      8 #include <algorithm>
      9 #include <string>
     10 #include <vector>
     11 #include <queue>
     12 #include <map>
     13 #include <set>
     14 #include <sstream>
     15 #include <iomanip>
     16 using namespace std;
     17 typedef long long ll;
     18 typedef unsigned long long ull;
     19 const ll inff = 0x3f3f3f3f3f3f3f3f;
     20 #define FOR(i,a,b) for(int i(a);i<=(b);++i)
     21 #define FOL(i,a,b) for(int i(a);i>=(b);--i)
     22 #define REW(a,b) memset(a,b,sizeof(a))
     23 #define inf int(0x3f3f3f3f)
     24 #define si(a) scanf("%d",&a)
     25 #define sl(a) scanf("%lld",&a)
     26 #define sd(a) scanf("%lf",&a)
     27 #define ss(a) scanf("%s",a)
     28 #define mod ll(6666666)
     29 #define pb push_back
     30 #define eps 1e-6
     31 #define lc d<<1
     32 #define rc d<<1|1
     33 #define Pll pair<ll,ll>
     34 #define P pair<int,int>
     35 #define pi acos(-1)
     36 ll n,p,g,id[2000008],m,ans[5000008],pr[1000008],prime[1000008],qw[1000008],tot;
     37 ll a[100008],jc[15],inv[100008],mm=1e9+7,vis[15],sss[100008];
     38 char s[15],ss[5008];
     39 inline int read()
     40 {
     41     int X=0,w=0; char ch=0;
     42     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
     43     while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
     44     return w?-X:X;
     45 }
     46 void init(int n)
     47 {
     48     int i,j;
     49     tot=0;
     50     prime[1]=1;
     51     for(i=2;i<=n;i++)
     52     {
     53         if(!prime[i]) prime[i]=pr[tot++]=i;
     54         for(j=0;j<tot&&pr[j]*i<=n;j++)
     55         {
     56             prime[i*pr[j]]=pr[j];
     57             if(i%pr[j]==0) break;
     58         }
     59     }
     60 }
     61 ll gmod(ll a,ll b,ll p)
     62 {
     63     ll res=1;
     64     while(b)
     65     {
     66         if(b&1) res=res*a%p;
     67         a=a*a%p,b>>=1;
     68     }
     69     return res;
     70 }
     71 int root(int x)
     72 {
     73     int f,phi=x-1;qw[0]=0;
     74     for(int i=0;phi&&i<tot;i++)
     75     {
     76         if(phi%pr[i]==0)
     77         {
     78             qw[++qw[0]]=pr[i];
     79             while(phi%pr[i]==0) phi/=pr[i];
     80         }
     81     }
     82     for(int g=2;g<=x-1;g++)
     83     {
     84         f=1;
     85         for(int i=1;i<=qw[0];i++)
     86          if(gmod(g,(x-1)/qw[i],x)==1) {f=0;break;}
     87         if(f) return g;
     88     }
     89     return 0;
     90 }
     91 struct CP{
     92     double x,y;
     93     CP(){} CP(double a,double b):x(a),y(b){}
     94     CP operator+(const CP&r) const{return CP(x+r.x,y+r.y);}
     95     CP operator-(const CP&r) const{return CP(x-r.x,y-r.y);}
     96     CP operator*(const CP&r) const{return CP(x*r.x-y*r.y,x*r.y+y*r.x);}
     97 }b[5000008],t;
     98 inline void Swap(CP&a,CP&b) {t=a;a=b;b=t;}
     99 inline void fft(CP*a,int f,int n)
    100 {
    101     int i,j,k;
    102     for(i=j=0;i<n;i++)
    103     {
    104         if(i>j) Swap(a[i],a[j]);
    105         for(k=n>>1;(j^=k)<k;k>>=1);
    106     }
    107     for(int i=1;i<n;i<<=1)
    108     {
    109         CP wn(cos(pi/i),f*sin(pi/i));
    110         for(int j=0;j<n;j+=i<<1)
    111         {
    112             CP w(1,0);
    113             for(int k=0;k<i;k++,w=w*wn)
    114             {
    115                 CP x=a[j+k],y=w*a[i+j+k];
    116                 a[j+k]=x+y;a[i+j+k]=x-y;
    117             }
    118         }
    119     }
    120     if(f==-1) FOR(i,0,n) a[i].x/=n;
    121 }
    122 void rkt(ll n,ll k)
    123 {
    124     ll t,ty=0;
    125     REW(vis,0);
    126     n--;
    127     FOR(i,0,k-1)
    128     {
    129         t=n/jc[k-i-1];
    130         n%=jc[k-i-1];
    131         for(ll j=0,pos=0;;j++,pos++)
    132         {
    133             if(vis[pos]) j--;
    134             if(j==t){vis[pos]=1;s[ty++]=('a'+pos+1);break;}
    135         }
    136     }
    137 }
    138 int main()
    139 {
    140     cin.tie(0);
    141     cout.tie(0);
    142     freopen("date1.in","r",stdin);
    143     freopen("date1.out","w",stdout);
    144     int tt;
    145     cin>>tt;
    146     ss['b']='b',ss['c']='c',ss['d']='h',ss['e']='j',ss['f']='k',ss['g']='l';
    147     ss['h']='m',ss['i']='w',ss['j']='x',ss['k']='y',ss['l']='z';
    148     jc[0]=jc[1]=1;
    149     for(ll i=2;i<=12;i++) jc[i]=jc[i-1]*i;
    150     inv[1]=1;
    151     FOR(i,2,100005)  inv[i]=(mm-mm/i)*inv[mm%i]%mm;
    152     init(100000);
    153     while(tt--)
    154     {
    155         cin>>n>>p;
    156         g=root(p);
    157         ll tmp=1,qw=0,er,sum=1;
    158         for(int i=1;i<p-1;i++)
    159         {
    160             tmp=tmp*g%p;
    161             id[tmp]=i;
    162         }
    163         er=m=p-1;
    164         for(m=er+m,er=1;er<=m;er<<=1);
    165         FOR(i,0,er+1) b[i].x=b[i].y=0.0,ans[i]=0;
    166         FOR(i,1,n)
    167         {
    168             a[i]=read();
    169             if(!(a[i]%p)) qw++;
    170             else b[id[a[i]%p]].x+=1.0;
    171         }
    172         fft(b,1,er);
    173         FOR(i,0,er) b[i]=b[i]*b[i];
    174         fft(b,-1,er);
    175         for(int i=0;i<2*p;i++) ans[i%(p-1)]+=(ll)(b[i].x+0.2);
    176         for(int i=1;i<=n;i++)
    177         {
    178             if(a[i]>=p) er=0;
    179             else if (a[i]==0) er=2*qw*n-qw*qw;
    180             else er=ans[id[a[i]]];
    181             sss[i]=er;
    182         }
    183         er=0;
    184         for(int i=0;i<n;i++)
    185         {
    186             er=(er+sum*sss[i+1])%mm;
    187             sum=(sum*(n-1-i)%mm)*inv[i+1]%mm;
    188         }
    189         //cout<<er<<endl;
    190         er=((er%mod)*2333333)%mod;
    191         if(er==0) {puts("-1");continue;}
    192         rkt(er,11);
    193         for(int i=0;i<11;i++) printf("%c",ss[s[i]]);
    194         puts("");
    195     }
    196     return 0;
    197 }
    View Code

     

    H: 简单题*10000

    Description

    已知一排硬币中有n个硬币正面朝上,输入正面朝上的硬币的位置ai(可能重复)。
    两人轮流操作,每次操作可以翻转1,2,或则3枚硬币(不一定连续),其中翻转的最右的硬币必须是正面朝上的,最后不能翻转的为负

    Input

    第一行输入一个组数t(t ≤ 100)。

    对于每组数据第一行有一个正整数N(0 ≤ N ≤ 5000)。

    第二行N个非负整数c1,c2,...,cN(0 ≤ ai ≤ 1e9)。

    Output

    如果先手必胜输出Yes,否则输出No。

    Examples

    Input

    2

    1

    0

    4

    0 1 2 3

    Output

    Yes

    No

    正确解法:

    定义硬币全反时的sg为0,现在单个游戏就是只有一枚硬币朝上,其余都是反,其他情况都可以由单一游戏组合而成。如果位置i有一个正面朝上的硬币,其余都是反,那么这枚硬币翻过来的时候,它可以到达的局面是1、sg = 0   2、sg(j)j位置的硬币朝上,其余都是反(j<i) 3、出现两个正面朝上的硬币,变成组合游戏sg(j)和sg(k)。我们把sg函数打表出来就可以找到规律。(hdu3537)

    初始编号从0开始。

    当N==1时,硬币为:正,先手必胜,所以sg[0]=1.

    当N==2时,硬币为:反正,先手必赢,先手操作后可能为:反反或正反,方案数为2,所以sg[1]=2。

    当N==3时,硬币为:反反正,先手必赢,先手操作后可能为:反反反、反正反、正反正、正正反,方案数为4,所以sg[2]=4。

    位置x:0  1  2  3  4   5    6   7    8     9  10  11  12  13  14...

    sg[x]:  1  2  4  7  8  11 13 14  16  19  21  22  25  26  28…

    看上去sg值为2x或者2x+1。我们称一个非负整数为odious,当且仅当该数的二进制形式的1出现的次数是奇数,否则称作evil。所以1,2,4,7是odious因为它们的二进制形式是1,10,100,111.而0,3,5,6是evil,因为它们的二进制形式是0,11,101,110。而上面那个表中,貌似sg值都是odious数。所以当2x为odious时,sg值是2x,当2x是evil时,sg值是2x+1.

    这样怎么证明呢?我们会发现发现,

                                                         evil^evil=odious^odious=evil

                                                         evil^odious=odious^evil=odious

    假设刚才的假说是成立的,我们想证明下一个sg值为下一个odious数。注意到我们总能够在第x位置翻转硬币到达sg为0的情况;通过翻转第x位置的硬币和两个其它硬币,我们可以移动到所有较小的evil数,因为每个非零的evil数都可以由两个odious数异或得到;但是我们不能移动到下一个odious数,因为任何两个odious数的异或都是evil

    假设在一个Mock Turtles游戏中的首正硬币位置x1,x2,…,xn是个P局面,即sg[x1]^…^sg[xn]=0.那么无可置疑的是n必定是偶数,因为奇数个odious数的异或是odious数,不可能等于0。而由上面可知sg[x]是2x或者2x+1,sg[x]又是偶数个,那么x1^x2^…^xn=0。相反,如果x1^x2^…^xn=0且n是偶数,那么sg[x1]^…^sg[xn]=0。这个如果不太理解的话,我们可以先这么看下。2x在二进制当中相当于把x全部左移一位,然后补零,比如说2的二进制是10,那么4的二进制就是100。而2x+1在二进制当中相当于把x全部左移一位,然后补1,比如说2的二进制是10,5的二进制是101。现在看下sg[x1]^…^sg[xn]=0,因为sg[x]是2x或者2x+1,所以式子中的2x+1必须是偶数个(因为2x的最后一位都是0,2x+1的最后一位都是1,要最后异或为0,2x+1必须出现偶数次)

     
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <bitset>
     5 #include <cmath>
     6 #include <cctype>
     7 #include <iostream>
     8 #include <algorithm>
     9 #include <string>
    10 #include <vector>
    11 #include <queue>
    12 #include <map>
    13 #include <set>
    14 #include <sstream>
    15 #include <iomanip>
    16 using namespace std;
    17 typedef long long ll;
    18 typedef unsigned long long ull;
    19 const ll inff = 0x3f3f3f3f3f3f3f3f;
    20 #define FOR(i,a,b) for(int i(a);i<=(b);++i)
    21 #define FOL(i,a,b) for(int i(a);i>=(b);--i)
    22 #define REW(a,b) memset(a,b,sizeof(a))
    23 #define inf int(0x3f3f3f3f)
    24 #define si(a) scanf("%d",&a)
    25 #define sl(a) scanf("%lld",&a)
    26 #define sd(a) scanf("%lf",&a)
    27 #define ss(a) scanf("%s",a)
    28 #define mod ll(6666666)
    29 #define pb push_back
    30 #define eps 1e-6
    31 #define lc d<<1
    32 #define rc d<<1|1
    33 #define Pll pair<ll,ll>
    34 #define P pair<int,int>
    35 #define pi acos(-1)
    36 int n,a[100008];
    37 int as(int x)
    38 {
    39     int k=0;
    40     while (x)
    41     {
    42         if (x&1) k++;
    43         x>>=1;
    44     }
    45     return !(k&1);
    46 }
    47 int main()
    48 {
    49     cin.tie(0);
    50     cout.tie(0);
    51     //freopen("game001.in","r",stdin);
    52     //freopen("game001.out","w",stdout);
    53     int tt;
    54     cin>>tt;
    55     while(tt--)
    56     {
    57         si(n);
    58         FOR(i,1,n) si(a[i]);
    59         sort(a+1,a+n+1);
    60         int k=unique(a+1,a+n+1)-a-1,s=0;
    61         FOR(i,1,k)
    62         {
    63             a[i]*=2ll;
    64             if(as(a[i])) a[i]++;
    65             s^=a[i];
    66         }
    67         if(s) puts("Yes");
    68         else puts("No");
    69     }
    70     return 0;
    71 }
    View Code

     

    I: 水题

    Description

    史努比最爱水题了,他知道现在他要挑战的是一道超级大水题哦。不过因为太水了,而且他又很懒,所以把这道水题推给了你们。

    有n个(不包括ZSTU和火车东站)车站介于ZSTU和火车东站之间,一共有m辆公交车往返于这些车站和火车东站。每个车站假设可以站无数个人,每辆车最多承载H[i]个人,经过S[i]个车站。假设一辆车依次经过1,2,3,这三个车站,那么它将一直往复1->2->3->1->2...现在认为车从一个站到下一个站要花费1个小时,人只能在车站或ZSTU,火车东站上下车,初始时有k个人在ZSTU(0站),所有的车都在初始站(所给车站的第一个车站为初始站),现在问你们最快让全部人从ZSTU到火车东站要多少小时。所有车同时运行。

    Input

    第一行有一个T<=10,表示T组测试样例,第二行三个数n(车站数目),m(车数目),k(人数),(n<=13,m<=20,k<=50);接下来的m行给出车信息,每行给出H[i](能承载的最大人数),S[i](经过的车站数目),还有依次给出S[i]个车站编号。ZSTU用0编号表示,火车东站用-1表示。

    Output

    若无解则输出-1,否则逐行输出答案。

    Examples

    Input

    2

    2 2 1

    1 3 0 1 2

    1 3 1 2 -1

    2 3 3

    1 2 0 2

    1 2 1 2

    1 2 1 -1

    Output

    5

    7

    正确解法:

    第一个样例,一人从0站乘坐1号公交车途径1站,到2站下车,花费2S;此时2号车位于-1站,再经过2S,2号车从-1站途径1站到2站,人上2号车再经过1S到达-1站,共花费5S。或者一人从0站乘坐一号公交车到1站下车,花费1S,此时2号车位于2站,再经过2S到1站,人上2号车再经过2S到达-1站,共花费5S。

    首先判断学校到火车东站能不能到站,即是否在同一个集团里面,用并查集就可以了。然后跑网络流,网络流跑一次后会更改原来储存的边的信息,因此可以枚举时间进行网络流,按照时间建边,在上一个时间段跑网络流的基础上,继续建图在继续跑网络流,将每次的最大流加起来直到总和大于等于k就可以返回当前天数了。

    具体操作是将第i-1小时的第j个车的信息向第i小时的第j个车进行连边,容量为INF,将每辆车第i-1小时所待的公交车站向第i小时所待的公交车站连边,容量为车的最大载人数。

     

      1 #include <bits/stdc++.h>
      2 //CLOCKS_PER_SEC
      3 #define se second
      4 #define fi first
      5 #define ll long long
      6 #define lson l,m,rt<<1
      7 #define rson m+1,r,rt<<1|1
      8 #define Pii pair<int,int>
      9 #define Pli pair<ll,int>
     10 #define ull unsigned long long
     11 #define pb push_back
     12 #define fio ios::sync_with_stdio(false);cin.tie(0)
     13 const double Pi=3.14159265;
     14 const int N=1e3+5;
     15 const ull base=163;
     16 const int INF=0x3f3f3f3f;
     17 using namespace std;
     18 int n,m,k,s,t;
     19 int head[10100],to[100010],cur[10100],nx[100010];
     20 int cap[100010];
     21 int tot=0;
     22 void add(int x,int y,int c){
     23     to[tot]=y;
     24     nx[tot]=head[x];
     25     cap[tot]=c;
     26     head[x]=tot++;
     27     
     28     to[tot]=x;
     29     nx[tot]=head[y];
     30     cap[tot]=0;
     31     head[y]=tot++;
     32 }
     33 void init(int n){
     34     tot=0;
     35     memset(head,-1,sizeof(head));
     36 }
     37 int d[N];
     38 int bfs(){
     39     memset(d,-1,sizeof(d));
     40     queue<int>q;
     41     q.push(s);
     42     d[s]=1;
     43     while(!q.empty()){
     44         int u=q.front();q.pop();
     45         for(int i=head[u];~i;i=nx[i]){
     46             int v=to[i];
     47             if(d[v]==-1&&cap[i]>0){
     48                 d[v]=d[u]+1;
     49                 q.push(v);
     50             }
     51         }
     52     }
     53     return d[t]!=-1;
     54 }
     55 int dfs(int s,int a){
     56     if(s==t||a==0)return a;
     57     int flow=0,f;
     58     for(int &i=cur[s];~i;i=nx[i]){
     59         int v=to[i];
     60         if(d[s]+1==d[v] && cap[i]>0 && (f=dfs(v,min(a,cap[i])))>0){
     61             flow+=f;
     62             cap[i]-=f;
     63             cap[i^1]+=f;
     64             a-=f;
     65             if(a==0)break;
     66         }
     67     }
     68     return flow;
     69 }
     70 int dinic(){
     71     int ans=0;
     72     while(bfs()){
     73         for(int i=0;i<=1000;i++)cur[i]=head[i];
     74         while(int di=dfs(s,INF)){
     75             ans+=di;
     76         }
     77     }
     78     return ans;
     79 }
     80 int ship[N][N];
     81 int num[N];
     82 int r[N];
     83 int fa[N];
     84 int F(int x){
     85     return fa[x]==x?x:fa[x]=F(fa[x]);
     86 }
     87  
     88 bool check(int x,int y){
     89     if(F(x)==F(y))return 1;
     90     else return 0;
     91 }
     92 int cal(int a,int d){
     93     return d*n+a;
     94 }
     95 void solve(){
     96     int flow=0;
     97     int i;
     98     init(n);// n -1     n-1   0
     99     add(s,cal(n-1,0),INF);
    100     add(cal(n,0),t,INF);
    101     for(i=1;flow<k;i++){
    102         add(s,cal(n-1,i),INF);add(cal(n,i),t,INF);
    103         for(int j=1;j<=n;j++){
    104             add(cal(j,i-1),cal(j,i),INF);
    105         }
    106         for(int j=1;j<=m;j++){
    107             int a=(i-1)%num[j]+1;
    108             int b=i%num[j]+1;
    109             add(cal(ship[j][a],i-1),cal(ship[j][b],i),r[j]);
    110         }
    111         flow+=dinic();
    112         
    113     }
    114    printf("%d
    ",i-1);
    115 }
    116 int main(){
    117      // clock_t start, end;
    118     int T;scanf("%d",&T);
    119     while(T--){
    120         s=0,t=1000;
    121         scanf("%d%d%d",&n,&m,&k);
    122         for(int i=0;i<=n+2;i++)fa[i]=i;
    123         for(int i=1;i<=m;i++){
    124             scanf("%d%d",&r[i],&num[i]);
    125             for(int j=1;j<=num[i];j++){
    126                 scanf("%d",&ship[i][j]);
    127                 if(ship[i][j]==0)ship[i][j]=n+1;
    128                 if(ship[i][j]==-1)ship[i][j]=n+2;
    129                 if(j>1){
    130                     fa[F(ship[i][j-1])]=F(ship[i][j]);
    131                 }
    132             }
    133         }
    134         n+=2;
    135         if(check(n, n-1)){
    136             solve();
    137         }
    138         else{
    139             printf("0
    ");
    140         }
    141     }
    142     // end = clock();
    143     // cout << "time :"<<(double)(end - start) / CLOCKS_PER_SEC << endl;
    144     return 0;
    145 }
    146 /*
    147 */
    View Code

     

    K: 快乐树论

    Description

    曾经有一位伟大的皇帝,他拥有n座城池并用n-1条无向道路相连,每条道路均有一个确定的长度和两个端点,保证城池与城池之间互达。有一天,皇帝决定将其中一条路拆掉,并重新将这条道路以同样的长度搭在两座城池之间,皇帝可能将这条路拆了又重新建在原处。现在皇帝想问问你,在只拆掉一条道路并重新建造一条同样长的在两座城池之间后,任意两个城池之前的距离和最小为多少呢?

    Input

    第一行输入一个n代表皇帝有n座城池,接下来n-1行输入a,b,c代表城池a,b之间有一条长为c的道路。 (2 ≤ n ≤ 5000, 1 ≤ ai, bi ≤ n, ai ≠ bi, 1 ≤ wi ≤ 106)

    Output

     输出一行任意两城池之间的最小距离和。

    Examples

    Input

    输入样例1:

    3

    1 2 2

    1 3 4

    输入样例2:

    6

    1 2 1

    2 3 1

    3 4 1

    4 5 1

    5 6 1

    输入样例3:

    6

    1 3 1

    2 3 1

    Output

    12

    29

    85

    正确解法:

    具体证明参考:https://blog.csdn.net/zhoufenqin/article/details/9821617

     1 #include<bits/stdc++.h>
     2  
     3 #define fi first
     4 #define se second
     5 #define pb push_back
     6  
     7 using namespace std;
     8  
     9 typedef long long ll;
    10 typedef pair<ll,ll> Pll;
    11  
    12 const ll LLMAX=2e18;
    13 const int MAXN=1e6+10;
    14  
    15 struct node{
    16     int u,v;
    17     ll w;
    18 }in[MAXN];
    19  
    20 ll dp[MAXN][3];
    21 vector<Pll>G[MAXN];
    22  
    23 void dfs(int u,int pre){
    24     dp[u][0]=dp[u][1]=dp[u][2]=0;
    25     for(int i=0;i<G[u].size();i++){
    26         int v=G[u][i].fi,w=G[u][i].se;
    27         if(v==pre)   continue;
    28         dfs(v,u);
    29         dp[u][2]+=dp[v][2]+dp[v][1]*dp[u][0]+dp[v][0]*dp[u][1]+dp[u][0]*dp[v][0]*w;
    30         dp[u][1]+=dp[v][1]+dp[v][0]*w;
    31         dp[u][0]+=dp[v][0];            
    32     }
    33     dp[u][0]++;
    34     dp[u][2]+=dp[u][1];
    35 }
    36  
    37 void solve(int u,int pre,ll &ans){
    38     ans=min(ans,dp[u][1]);
    39     for(int i=0;i<G[u].size();i++){
    40         int v=G[u][i].fi,w=G[u][i].se;
    41         if(v==pre)  continue;
    42         dp[v][1]=dp[v][1]+(dp[u][1]-dp[v][1]-w*dp[v][0])+(dp[u][0]-dp[v][0])*w;
    43         dp[v][0]=dp[u][0];
    44         solve(v,u,ans);
    45     }
    46 }
    47  
    48 int main(void)
    49 {
    50     ios::sync_with_stdio(false);    cin.tie(0);
    51     ll n,ans=LLMAX;  cin>>n; 
    52     for(int i=1;i<n;i++){
    53         ll x,y,v;  cin>>x>>y>>v;    
    54         in[i].u=x,in[i].v=y,in[i].w=v;
    55         G[x].pb(Pll(y,v)),G[y].pb(Pll(x,v));
    56     }
    57     for(int i=1;i<n;i++){
    58         ll ans1=LLMAX,ans2=LLMAX,u=in[i].u,v=in[i].v,w=in[i].w;
    59         dfs(u,v);   solve(u,v,ans1);
    60         ll len1=(n-dp[u][0])*ans1+dp[u][2];
    61         dfs(v,u);   solve(v,u,ans2);
    62         ll len2=(n-dp[v][0])*ans2+dp[v][2];
    63         ans=min(ans,len1+len2+dp[u][0]*dp[v][0]*w);
    64     }
    65     cout<<ans<<endl;
    66     return 0;
    67 }
    View Code

    L: 快乐数论

    Description

    给出正整数n,k,要求使正整数n拆分成若干个正整数的和,并且使得拆分后的数中相同的数的出现次数小于k次。

    Input

    第一行输入T,共有T组测试样例,接下来2~T+1行,每行输入n,k。 1<=n,k,T<=10^5

    Output

    输出T行,每行对应的拆分方案,最后答案取模1e9+7

    Examples

    Input

    4

    4 2

    4 3

    4 4

    4 5

    Output

    2

    4

    4

    5

    正确解法:

    n=4,k=2时,可拆分成4=4,4=1+3

    n=4,k=3时,可拆分成4=1+2+1,4=2+2,4=1+3,4=4

     

     1 #include<bits/stdc++.h>
     2  
     3 using namespace std;
     4  
     5 typedef long long  ll;
     6  
     7 const int MOD=1e9+7;
     8 const int MAXN=1e6+10;
     9  
    10 ll p[MAXN];
    11  
    12 void init(){
    13     p[0]=1;
    14     for(ll i=1;i<=100000;i++){
    15         for(ll j=1,w=1;w<=i;j++,w=(3*j*j+j)/2)
    16             if(j&1) p[i]=(p[i]+p[i-w])%MOD;
    17             else    p[i]=((p[i]-p[i-w])%MOD+MOD)%MOD;
    18         for(ll j=1,w=2;w<=i;j++,w=(3*j*j-j)/2)
    19             if(j&1) p[i]=(p[i]+p[i-w])%MOD;
    20             else    p[i]=((p[i]-p[i-w])%MOD+MOD)%MOD;
    21     }
    22 }
    23  
    24 ll solve(ll n,ll k){
    25     ll ans=p[n];
    26     for(ll j=1,w=k;w<=n;j++,w=k*(3*j*j+j)/2)
    27         if(j&1) ans=((ans-p[n-w])%MOD+MOD)%MOD;
    28         else    ans=(ans+p[n-w])%MOD;
    29     for(ll j=1,w=2*k;w<=n;j++,w=k*(3*j*j-j)/2)
    30         if(j&1) ans=((ans-p[n-w])%MOD+MOD)%MOD;
    31         else    ans=(ans+p[n-w])%MOD;
    32     return ans;
    33 }
    34  
    35 int main(void)
    36 {
    37     init();
    38     int T;  cin>>T;
    39     while(T--){
    40         ll n,k;   scanf("%lld%lld",&n,&k);
    41         printf("%lld
    ",solve(n,k));
    42     }
    43     return 0;
    44 }
    View Code

     

     M: 看电影

    Description

    wjh要去看电影,邀请了lmb,xxb,cly,yzj,ckx等人,最后有k个人同意一起去。要去的电影院的位置是矩阵型的,其中’#’表示已经被人预定了,’*’表示空位,他们打算挑同一行或者同一列连续的座位坐在一起,现在给出k和位置的预定请况,试问有几种坐位置的方法。

    Input

    第一行输入两个数n和k,n表示电影院的位置是n*n的。(0<n<=10,0<=k<10)
    接下在n行,每行n个字符,表示位置的预订情况。

    Output

     一行输出有几种坐法。

    Examples

    Input

    4 1

    **##

    *###

    ####

    ####

    Output

    4

    正确解法:

    暴力纵向横向搜索一下。

    当k为0时,答案要除2。

    No matter how you feel, get up , dress up , show up ,and never give up.
  • 相关阅读:
    javascript数组/对象数组的深浅拷贝问题
    Vue packages version mismatch
    关于Echarts的使用和遇到的问题
    webpack 打包 todolist 应用
    Js正则学习笔记
    Vue项目多域名跨域
    Vuex的简单应用
    css3实现饼状图进度及环形进度条
    浏览器缓存机制
    去除滚动条
  • 原文地址:https://www.cnblogs.com/Kaike/p/9905392.html
Copyright © 2011-2022 走看看