【pG&&CYH-01】元旦联欢会

题解:

t1:

题解是循环矩阵

但我并没有往矩阵上想下去。。。

这个东西比较显然的是可以把它看成生成函数

然后就可以任意模数fft了

复杂度比题解优 $nlog^2$

t2:

随便推推式子就好了

t3:

矩阵的一般套路

维护$f(n-1),f(n-2),{f(n-1)}^2,{f(n-2)}^2,f(n-1)*f(n-2)$

他们之间是可以递推的

t4:不会

t5:

这种题目比较显然是找规律

然后会发现2^i-2^i+1的差是等差数列

暴力做是nlogn的

我们可以利用一些优化做到O(n)

对2^n的打表(当然我oeis了一下是有递推式的)

然后快速查某个数有几位(builtin 但noi赛事都不能用于是我就手动实现了)

然而这题空间开16m不知道意义何在

fread的快读和快输都不能用。。。

不用快读快输显然过不了

还得从网上拉了个getchar的。。很烦。。

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define ll long long
namespace IO{
/*  char ss[1<<24],*A=ss,*B=ss;
  IL char gc()
  {
    return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
  }
  template<class T>void read(T &x)
  {
    rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
    while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; 
  }*/
  char sr[1<<24],z[20];int C=-1,Z=0;
  template<class T>void wer(T x)
  {
    if (x<0) sr[++C]='-',x=-x;
    while (z[++Z]=x%10+48,x/=10);
    while (sr[++C]=z[Z],--Z);
  }
  IL void wer1() {sr[++C]=' ';}
  IL void wer2() {sr[++C]='
';}
};
using namespace IO;
const int mo=1e9+7;
int wa[100000];
ll p[70]={0,0ll, 2ll, 14ll, 70ll, 310ll, 1302ll, 5334ll, 21590ll, 86870ll, 348502ll, 1396054ll, 5588310ll, 22361430ll, 89462102ll, 357881174ll, 431590223ll, 726491955ll, 906229948ll, 625444057ll, 502824788ll, 13396288ll, 57779454ll, 239506422ll, 974802902ll, 932766017ll, 798172909ll, 326909341ll, 576072811ll, 841162140ll, 438390354ll, 901045041ll, 899147409ll, 186524142ll, 925965631ll, 63600624ll, 973878754ll, 334467499ll, 215775006ll, 618910060ll, 987260307ll, 972281364ll, 935605751ll, 835383617ll, 527455717ll, 481665396ll, 670346656ll, 168756770ll, 649767409ll, 548550282ll, 93162436ll, 170572390ll, 278134854ll, 304230006ll, 600301213ll, 167967225ll, 205393676ll, 888624265ll, 688596163ll, 22582881ll, 626728026ll};
IL int getws(ll x)
{
  if (x>>48) return 48+wa[x>>48];
  if (x>>32) return 32+wa[x>>32];
  if (x>>16) return 16+wa[x>>16];
  return wa[x];
}
IL ll js(ll x)
{
  int k=getws(x);
  ll now=1ll<<(k-1);
  return (p[k-1]+((x-now)%mo)*((x-now+1)%mo)%mo)%mo;
}

ll read(){
    ll w=1,q=0;char ch=' ';
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')q=q*10+ch-'0',ch=getchar();
    return w*q;
}
void write(ll x)
{
    if(x<0){putchar('-');x=~(x-1);}
    int s[20],top=0;
    while(x){s[++top]=x%10;x/=10;}
    if(!top)s[++top]=0;
    while(top)putchar(s[top--]+'0');
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("2.out","w",stdout);
  rep(i,1,65538) wa[i]=wa[i>>1]+1;
  int n;
  ios::sync_with_stdio(false);
  n=read();
  rep(i,1,n)
  {
    ll k;
    k=read();
    write(js(k));
    printf("
"); 
  }
  return 0; 
}
View Code

 t6:

数据范围写成这样出题人真的是nb

首先每个点都可以用组合数表示出来

然后再推推式子就得到全部的了

原文地址:https://www.cnblogs.com/yinwuxiao/p/10207928.html