1. 程式人生 > >ZOJ - 4056 Press the Button 青島網路賽(思路)

ZOJ - 4056 Press the Button 青島網路賽(思路)

題意
給你6個數,A,B,C,D,T,V,給你一盞燈,它每隔V+0.5秒就會熄滅,A表示的是你每隔A秒可以拍燈B 下,如果燈是滅的,我們就讓燈變亮,如果燈是亮的的話,我們就讓分數+1,並將燈重新設定為每隔V+0.5秒熄滅,問你T秒之後的得分是多少。
思路
首先我們可以算出在T秒中總共拍了多少次燈,他是 ( t / a )

b + ( t / c ) d +
b + d 1 (t/a) * b + (t/c) * d + b+d-1 ,怎麼的出來的?就是 t
t
秒中有多少個 a a 就拍幾次,同理 b b 也是,然後0秒的時候兩人同時拍是 b + d 1 b+d-1 。之後我們可以看出就是,他是有迴圈節的,每LCM之後就有一個迴圈,那麼我們得到一個迴圈節之後就能算出所有的了,現在的問題就是如何得到一個迴圈節的分數?首先我們篩出 a a b b 的倍數,排序去重之後兩兩相減,如果差值大於 v v 就表示我要浪費一次機會去把燈開啟,那麼我們最後就用總共拍了多少次燈-浪費的次數就能得到答案了
程式碼

#include <bits/stdc++.h>
using namespace std;
#define int long long
vector<long long>V; 
signed main()
{
	int T;
	scanf("%lld",&T);
	while(T--)
	{
		int a,b,c,d,v,t;
		scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&v,&t);
		long long te = __gcd(a,c);
		long long lcm = a*c/te;
		V.clear();		
		for(int i = 0 ; i <= lcm ; i += a) V.push_back(i);
		for(int i = 0 ; i <= lcm ; i += c) V.push_back(i);
		sort(V.begin() , V.end());
		V.erase(unique(V.begin() , V.end()) , V.end());
		int tmp = 0;
		for(int i = 1 ; i < V.size() ; i++)
		{
			if(V[i] - V[i-1] > v) tmp ++;  
		}
		long long ans = (t/a) * b + (t/c) * d + b + d - 1; 
		long long cur = t/lcm; 
		ans = ans - cur*tmp; 
		long long la = t % lcm;
		for(int i = 1 ; V[i] <= la ; i++)
		{
			if(V[i] - V[i-1] > v) ans --;		
		}
		cout<<ans<<endl; 
	}
}