HDU 5475 An easy problem(网络赛水题)

题目链接:HDU 5475

题目大意:

一个数从1开始,有两种操作,1. 将这个数乘 y  (0<y< 1e9 ) 2.将这个数除以第 n个操作数的 y,题目保证第n个操作一定是第1种操作。

操作次数最多 1e5 。每次操作后输出 当前的数%m

解题步骤:

看题目通过率就知道很多人开始和我想得一样, 每次乘除之后取余。结果wa掉。后来仔细一想,题目要求的是输出的时候,输出这个数取模后的值,并没让这个数取模,  而且如果在1操作后保留取模后的值, 那么2操作的除法操作就会有错误。

想到这,就开始敲 JAVA大数了,提交T LE ,又试了一下 C++大数模拟 TLE 。。。

这时候脑子就开始胡思乱想了。

想到一个暴力的方法,每次乘法边乘边取模,遇到除法就从头更新一下(标记的位置不用再乘)。然而操作次数高达1e5, 就被否决了。

然后就是奇思妙想了,是不是DP? 还是哪种高深的数据结构?


今天百度了一下 发现暴力居然能过!暴力居然能过!居然能过!


暴力出奇迹啊! 其实这样的题目就应该果断来一发的!


当然网上也有线段树的做法。


源代码:


纯暴力代码 Exe.Time 3354MS

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<stack>
#include<vector>
using namespace std;
const int maxn = 100000 + 10;
typedef unsigned long long ll;
ll num[maxn];
struct node{
    ll a,b;
}no[maxn];
int qe[maxn];
bool vis[maxn];
int main(){
    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++){
        printf("Case #%d:\n",cas);
        int q,mod;
        memset(vis,0,sizeof(vis));
        scanf("%d%d",&q,&mod);
        int a;
        long long  ans = 1;
        for(int i=1;i<=q;i++){
            scanf("%d%d",&a,&qe[i]);
            if(a == 2){
                vis[i] = true; 
                vis[qe[i]] = true; //标记不用乘的位置。
                ans = 1; 遇到 2 就从头更新一遍。。。
                for(int j=1;j<i;j++){ 
                    if(!vis[j]){
                        ans=ans*qe[j];
                        ans%=mod;
                    }
                }
            }
            else{
                ans=ans*qe[i];
                ans%=mod;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

稍微优化的暴力代码 Exe.Time 2246MS


#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<stack>
#include<vector>
using namespace std;
const int maxn = 100000 + 10;
typedef unsigned long long ll;
ll num[maxn];
struct node{
	ll a,b;
}no[maxn];
int qe[maxn];
bool vis[maxn];
long long  x[maxn]; 用x储存当前的结果
int main(){
	int t;
	scanf("%d",&t);
	for(int cas=1;cas<=t;cas++){
		printf("Case #%d:\n",cas);
		int q,mod;
		memset(vis,0,sizeof(vis));
		scanf("%d%d",&q,&mod);
		int a;
		long long  ans = 1;
		x[0] = 1;
		for(int i=1;i<=q;i++){
			scanf("%d%d",&a,&qe[i]);
			if(a == 2){
				vis[i] = true;
				vis[qe[i]] = true;
				for(int j=qe[i];j<=i;j++){ 与纯暴力代码不同,从修改的位置开始更新到当前的i
					x[j] = x[j-1];
					if(vis[j])
						continue;
					x[j] = x[j]*qe[j];
					x[j] = x[j]%mod;
				}
			}
			else{
				x[i] = x[i-1]*qe[i];
				x[i]=x[i]%mod;
			}
			printf("%lld\n",x[i]);
		}
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值