1. 程式人生 > >【平安夜的胡策】訓練12.24(複數預處理+矩陣快速冪+dp)

【平安夜的胡策】訓練12.24(複數預處理+矩陣快速冪+dp)

這次比賽真是一言難盡,看來必須繼續努力。

這次比賽所有的“暴力”分就是170。

T1

這裡寫圖片描述
這裡寫圖片描述

題解:

喵喵喵在考場上看到這個題就mengbier了
首先你需要知道複數以及相關的運演算法則
我們手玩一通r的1~4次方,就可以發現r中總是含有7i,還有一個常數項
格式和ta要的x+y7i一樣呀
那麼我們就可以預處理出r223以內的a+b7i中的a和b,為什麼2^23呢?因為更大的1s就跑不出來了
我們預處理可不能一個一個手玩啊,可以參考複數的運演算法則
z1=a+biz2=c+di
z1z2=ac+adi+bci+bdi2=(acbd)+(ad+bc)i
然後暴力搜尋就好了

程式碼:

60pts

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
double a[25],b[25],x,y;bool fff=0;
int c[25];
void dfs(int t,double aa,double bb)
{
    if (aa==x && bb==y){fff=1; return;}
    if (t>23) return;
    for (int i=0;i<=1 && !fff;i++)
      if
(i==0) dfs(t+1,aa,bb); else { c[t]=i;dfs(t+1,aa+a[t],bb+b[t]); if (!fff) c[t]=0; } } int main() { freopen("verlauf.in","r",stdin); freopen("verlauf.out","w",stdout); scanf("%lf%lf",&x,&y); a[0]=1; b[0]=0; a[1]=-0.5; b[1]=0.5; for (int i=2;i<=23
;i++) { a[i]=a[i-1]*(-0.5)-7*b[i-1]*0.5; b[i]=a[i-1]*0.5+b[i-1]*(-0.5); } dfs(0,0,0); for (int i=0;i<=23;i++) if (c[i]) printf("%d ",i); }

T2

70pts

T3

這裡寫圖片描述
這裡寫圖片描述

題解:

考場上不知道怎麼腦抽,寫的dfs都不知道寫一個“科學”的暴力
f[i][j]表示第i位上選j這個數陣列的個數
注意預處理的時候第一位取誰都是可以的,都設為1

程式碼:

40pts

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int mod=1e9+7;
int n,m,f[1005][1005],a[1005];
int gcd(int a,int b){if (!b) return a;else return gcd(b,a%b);}
int main()
{
    freopen("geburtstag.in","r",stdin);
    freopen("geburtstag.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=a[1];i++) f[1][i]=1;
    for (int i=1;i<=n;i++)
      for (int j=1;j<=a[i];j++)
        for (int k=1;k<=a[i-1];k++)
          if (gcd(j,k)<=m) f[i][j]=(f[i][j]+f[i-1][k])%mod;
    int ans=0;
    for (int i=1;i<=a[n];i++) ans=(ans+f[n][i])%mod;
    printf("%d",ans);
}