爆int

这是记录犯过的蠢系列的第一篇:爆int
例子如下
题目是一道简单的二进制状态压缩DP:CodeForces - 580D
代码如下:

#include<iostream>
#include<cstring>
using namespace std;
long long a[300000][20];
long long rule[30][30];
long long w[30];
int main()
{
 long long n,m,ans,l,j,k,i,u,v,t,max;
 cin>>n>>m>>k;
 for (i=1;i<=n;i++)
  cin>>w[i];
 max=(1<<n)-1;
 memset(rule,0,sizeof(rule));
 for (i=1;i<=k;i++)
 {
  cin>>u>>v>>t;
  rule[u][v]=t;
 }
 for (i=1;i<=max;i++)
 for (j=1;j<=n;j++)
  a[i][j]=-1;
 for (j=1;j<=n;j++)
 {
  a[1<<(j-1)][j]=w[j];
 }
 for (k=1;k<=m-1;k++)
 {
  for (i=max;i>=1;i--)
  for (j=1;j<=n;j++)
  {
   if (a[i][j]!=-1)
   {
    for (l=1;l<=n;l++)
    {
     if ((i>>(l-1))%2==0) 
     {
      if (a[i+(1<<(l-1))][l]<a[i][j]+rule[j][l]+w[l])
      {
       a[i+(1<<(l-1))][l]=a[i][j]+rule[j][l]+w[l];
      }
     }
    }
    a[i][j]=-1;
   }
  }
 }      
 ans=0;
 for (i=1;i<=max;i++)
 for (j=1;j<=n;j++)
 if (ans<a[i][j]) ans=a[i][j];
 cout<<ans<<endl;
 return 0;
}

以上为AC代码 下方为WA代码

#include<iostream>
#include<cstring>
using namespace std;
long long a[300000][20];
int rule[30][30];
int w[30];
int main()
{
 int n,m,ans,l,j,k,i,u,v,t,max;
 cin>>n>>m>>k;
 for (i=1;i<=n;i++)
  cin>>w[i];
 max=(1<<n)-1;
 memset(rule,0,sizeof(rule));
 for (i=1;i<=k;i++)
 {
  cin>>u>>v>>t;
  rule[u][v]=t;
 }
 for (i=1;i<=max;i++)
 for (j=1;j<=n;j++)
  a[i][j]=-1;
 for (j=1;j<=n;j++)
 {
  a[1<<(j-1)][j]=w[j];
 }
 for (k=1;k<=m-1;k++)
 {
  for (i=max;i>=1;i--)
  for (j=1;j<=n;j++)
  {
   if (a[i][j]!=-1)
   {
    for (l=1;l<=n;l++)
    {
     if ((i>>(l-1))%2==0) 
     {
      if (a[i+(1<<(l-1))][l]<a[i][j]+rule[j][l]+w[l])
      {
       a[i+(1<<(l-1))][l]=a[i][j]+rule[j][l]+w[l];
      }
     }
    }
    a[i][j]=-1;
   }
  }
 }      
 ans=0;
 for (i=1;i<=max;i++)
 for (j=1;j<=n;j++)
 if (ans<a[i][j]) ans=a[i][j];
 cout<<ans<<endl;
 return 0;
}

虽然注意到了1e9爆int 当时计算过程中出现了int+long long 出错后检查了好久的算法

求模运算是一种常见的数学操作,在程序设计中也经常使用。它的主要作用是对两个整数相除后返回余数,而不是商本身。通过取模可以有效地控制数值范围,避免因数据过大而导致溢出问题(例如超出`int`类型的存储能力)。以下是关于“为何求模能防止`int`溢出”的详细解释: ### 核心原理 当处理大数字计算时,如果结果超出了系统所支持的数据类型大小限制(如`int`的最大值为2^31 - 1),就可能发生**溢出错误**。为了避免这种情况发生,我们可以对中间结果或最终结果应用取模操作。 #### 取模的好处: 1. **保持数值较小** 使用`(a + b) % MOD` 或 `(a * b) % MOD` 等形式,可以使每次运算的结果都被限定在一个固定范围内(由MOD确定),不会轻易突破上限。 2. **符合数学规律** 假设我们有一个固定的常量 `M` ,那么对于任意加法、乘法等基本算术运算有以下性质成立: - 加法规律:(A+B)%M = [(A%M)+(B%M)]%M - 减法规律:(A-B)%M = [(A%M)-(B%M)+M]%M (这里加了一个额外的M以防负数) - 乘法规律:(A*B)%M = [(A%M)*(B%M)]%M 因此,即便实际参与计算的大数非常庞大,只要每一步都及时地加以取模约束,则始终能够得到正确的有限长度的答案。 --- ### 示例说明 假设需要频繁累加许多较大正整数并保存到变量sum里,但如果单纯依靠直接叠加的方式很容易越界崩溃;此时引入mod机制就能很好地解决这个问题了。 ```cpp const int MOD=1e9+7; long long sum=0LL; // 初始化累积和为零,并声明成更大容量类型以免初期暂存阶段即告满 for(auto x : arr){ sum=(sum+x)%MOD; // 对每一次增加均做一次压缩限幅动作 } // 最终输出时仍只保留受控部分即可满足题意需求同时规避风险 cout << sum ; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值