• 2022/8/11 状压+矩阵快速幂


            今天肚子不舒服,做的题有点少,咋加上看了个状压加快速幂的题目,直接emo了,,,​

    活动地址:CSDN21天学习挑战赛

    701C - They Are Everywhere 双指针

    一开始用的是vector存坐标然后52个字母暴力遍历起点,T了,,

    然后又想了一个奇葩的优先队列每次弹出最小坐标,然后用最大坐标减去最小坐标更新答案,也T了,,但是没想到竟然冲到了73个样例

    最后看了题解的提示才想起双指针来,让r从1到n开始遍历,然后l为1,如果满足条件了,l就开始向右走,一直走到条件不满足为止,在此期间不断更新答案

    1. #include
    2. using namespace std;
    3. #define ll long long
    4. #define lowbit(i) ((i)&(-i))
    5. const ll mod=100000000;
    6. const int N = 2e5+5;
    7. ll n,m,vis[55];
    8. map<char,ll>mp;
    9. char s[100005];
    10. ll ans=1e18;
    11. int main(){
    12. for(char i='a';i<='z';i++) mp[i]=i-'a'+1;
    13. for(char i='A';i<='Z';i++) mp[i]=i-'A'+27;
    14. scanf("%lld%s",&n,s+1);
    15. for(int i=1;i<=n;i++){
    16. if(!vis[mp[s[i]]]) m++;
    17. vis[mp[s[i]]]=i;
    18. }
    19. memset(vis,0,sizeof(vis));
    20. ll l=1,cnt=0;
    21. for(int i=1;i<=n;i++){
    22. if(!vis[mp[s[i]]]) cnt++;
    23. vis[mp[s[i]]]++;
    24. if(cnt==m){
    25. while(l<=i){
    26. ans=min(ans,i-l+1);
    27. vis[mp[s[l]]]--;
    28. if(vis[mp[s[l]]]<=0) cnt--;
    29. l++;
    30. if(cntbreak;
    31. }
    32. }
    33. }
    34. printf("%lld\n",ans);
    35. system("pause");
    36. return 0;
    37. }

    1616C - Representative Edges

    可以发现公式就是等差数列求n项和,所以问题转化为至少修改几处可以使得该序列变为一个等差数列,首先n<=2是不用修改的,之后由于数据很小所以我们可以直接n方枚举,固定两个点求出d,然后暴力检查一共需要修改几处更新答案就可以了,注意检查时代码的写法,

    这样是不对的

    1. if(k
    2. else if(a[k]!=a[i]+(k-i)*d) sum++;

    但这样就对了

    1. if(k
    2. else if((a[k]-a[i])/(k-i)!=d) sum++;

    ac代码

    1. #include
    2. using namespace std;
    3. #define ll long long
    4. #define lowbit(i) ((i)&(-i))
    5. const ll mod=100000000;
    6. double eps=1e-8;
    7. const int N = 2e5+5;
    8. ll t,n;
    9. double a[110];
    10. ll ans=1e18;
    11. int main(){
    12. scanf("%lld",&t);
    13. while(t--){
    14. ans=1e18;
    15. scanf("%lld",&n);
    16. for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
    17. if(n<=2){
    18. printf("0\n");continue;
    19. }
    20. for(int i=1;i<=n;i++)
    21. for(int j=i+1;j<=n;j++){
    22. double d=(a[j]-a[i])/(j-i);
    23. ll sum=0;
    24. for(int k=1;k<=n;k++){
    25. if(k==i||k==j) continue;
    26. if(k
    27. else if((a[k]-a[i])/(k-i)!=d) sum++;
    28. }
    29. //cout<
    30. ans=min(ans,sum);
    31. }
    32. printf("%lld\n",ans);
    33. }
    34. system("pause");
    35. return 0;
    36. }

    P1357 花园 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 状压dp 矩阵快速幂

    哇,这题真的难搞,学完了矩阵快速幂再来看这个题的题解还是非常吃力,因为这个构造矩阵竟然是要通过类似状压dp的方式来构造,设f[i]为状态为i时可以构造出的方案数,矩阵mat[j][i]是用来求f[i]下一个状态的转移矩阵,通过类似状压dp的方式求出,初始状态是mat[i][i]=1,最后的答案就是mat[i][i]的总和

    题解 P1357 花园 - 琉璃想要变得可爱 - 洛谷博客

    1. #include
    2. using namespace std;
    3. #define ll long long
    4. #define lowbit(i) ((i)&(-i))
    5. const ll mod=1e9+7;
    6. double eps=1e-8;
    7. const int N = 2e5+5;
    8. ll n,m,K,t,ans;
    9. struct matrix{
    10. ll row,col;
    11. ll mat[35][35];
    12. matrix(){
    13. memset(mat,0,sizeof(mat));
    14. }
    15. void init(){
    16. *this=matrix();
    17. row=col=t;
    18. for(int i=0;i1;
    19. }
    20. matrix operator*(const matrix& a)const{
    21. matrix res=matrix();res.row=row,res.col=col;
    22. for(int i=0;i
    23. for(int j=0;j
    24. for(int k=0;k
    25. res.mat[i][j]=(res.mat[i][j]+mat[i][k]*a.mat[k][j]%mod)%mod;
    26. return res;
    27. }
    28. matrix matpow(ll b){
    29. matrix res=matrix();
    30. res.init();
    31. matrix base=*this;
    32. while(b){
    33. if(b&1) res=res*base;
    34. base=base*base;
    35. b>>=1;
    36. }
    37. return res;
    38. }
    39. };
    40. int main(){
    41. scanf("%lld%lld%lld",&n,&m,&K);
    42. t=1<
    43. matrix b=matrix();b.row=b.col=t;
    44. for(int i=0,j;i
    45. if(__builtin_popcount(i)>K) continue;
    46. j=i>>1;
    47. //表示j可以推出i
    48. b.mat[j][i]=1;
    49. j=(i>>1)|(1<<(m-1));
    50. if(__builtin_popcount(j)<=K)
    51. b.mat[j][i]=1;
    52. }
    53. matrix res=b.matpow(n);
    54. for(int i=0;i
    55. printf("%lld\n",ans);
    56. system("pause");
    57. return 0;
    58. }

    矩阵快速幂

    上面的题目用到了就来看一下

     

     

     

    Fibonacci Numbers - HDU 3117 - Virtual Judge (vjudge.net)矩阵快速幂

    这个题上一年就做过了,但是不大懂,今天又来做,有些地方还是不大会,所以看了题解理解的更深了,其实这题没啥难的,难就难在要输出前四位和后四位上

    斐波那契的通项公式 

    (感谢百度)

    减号后面的由于很小就不管了,前面的由于很大需要取对数化为小数保存起来,用的时候乘以10000就行

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. //HDU火车头
    17. //#include
    18. #define ll long long
    19. #define lowbit(x) ((x)&(-x))
    20. using namespace std;
    21. const ll mod=10000;
    22. double eps=1e-8;
    23. const int N = 2e5+5;
    24. ll n,t;
    25. struct matrix{
    26. ll row,col;
    27. ll mat[35][35];
    28. matrix(){
    29. memset(mat,0,sizeof(mat));
    30. }
    31. void init(){
    32. *this=matrix();
    33. row=col=t;
    34. for(int i=0;i1;
    35. }
    36. matrix operator*(const matrix& a)const{
    37. matrix res=matrix();res.row=row,res.col=col;
    38. for(int i=0;i
    39. for(int j=0;j
    40. for(int k=0;k
    41. res.mat[i][j]=(res.mat[i][j]+mat[i][k]*a.mat[k][j]);
    42. if(res.mat[i][j]>=100000000)
    43. res.mat[i][j]%=mod;
    44. }
    45. return res;
    46. }
    47. matrix matpow(ll b){
    48. matrix res=matrix();
    49. res.init();
    50. matrix base=*this;
    51. while(b){
    52. //cout<
    53. if(b&1) res=res*base;
    54. base=base*base;
    55. b>>=1;
    56. }
    57. return res;
    58. }
    59. };
    60. int main(){
    61. while(scanf("%lld",&n)!=EOF){
    62. if(!n){printf("0\n");continue;}
    63. t=2;
    64. matrix b=matrix();
    65. b.row=b.col=t;
    66. b.mat[0][0]=b.mat[0][1]=b.mat[1][0]=1;
    67. matrix ans=b.matpow(n-1);
    68. //cout<
    69. if(n<40) printf("%lld\n",ans.mat[0][0]);
    70. else{
    71. double x = log10(1 / sqrt(5)) + n * log10((1 + sqrt(5)) / 2.0);
    72. double y = x - (int)(x);//取小数是为了求科学计数法的1.xxxx
    73. int res = (int)1000LL*pow(10.0, y);
    74. cout << res << "...";
    75. printf("%0.4d\n",ans.mat[0][0]%mod);
    76. }
    77. }
    78. system("pause");
    79. return 0;
    80. }

  • 相关阅读:
    TypeScript笔记:接口
    深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
    Python —— 特殊场景处理(鼠标、键盘操作&文件上传)
    【金融】探究财务报告业绩增速与股价变动之间的关系--研报复现及深入探究
    什么是DevOps
    【深度学习21天学习挑战赛】8、卷积神经网络(认识Xception模型):动物识别
    C#中的Web抓取:避免被阻挡
    CALL命令无法在PowerShell中使用
    Mysql 学习总结(89)—— Mysql 库表容量统计
    【AI实践案例】基于Encoder-Decoder模型的Word Level英语到Marathi神经机器翻译
  • 原文地址:https://blog.csdn.net/weixin_52621204/article/details/126267729