T1
问题描述
蔡老板最近迷上了下取整函数,即 f(x)=⌊x⌋,它表示不大于 x 的最大整数。
例如:⌊3.6⌋=3,⌊2⌋=2,⌊−2.7⌋=−3。
蔡老板有一个有理数 x=pq,他用 x 制造了一个序列 a=⌊x⌋,⌊2x⌋,⌊3x⌋,…。形式化地说,ai=⌊x⋅i⌋。
为了研究这个序列的性质,他尤其关注序列里没有出现过的非负整数。
现在,他想考考你。请你告诉他序列里没有出现过的、第 k 小的非负整数。特别地,如果不存在 k 个这样的数,则答案为 −1。
蔡老板会向你提出 T 个相互独立的问题。
输入格式
第一行包含一个整数 T,表示蔡老板向你提出的问题数量。
接下来 T 行,每行 3 个整数 pi,qi,ki,代表了【问题描述】中的 p,q,k。
输出格式
对每次询问,输出一行一行整数,表示答案。
请注意:因为本题输入输出量过大,我们提供了一个快速输入输出的模板,见下发文件中的 fastio.cpp。这份代码重写了 cin, cout。用法是,你只需要把 fastio.cpp 里面的内容全部复制到你的代码里,然后在代码中正常使用 cin,cout 输入、输出即可。使用这份代码后,请不要用 ios::sync_with_stdio(0);,cin.tie(0); cout.tie(0) 等代码关闭同步。见 sample.cpp 作为一个示范。
思路
们二分答案。考虑0~mid里有多少数在序列里出现过。这个数量就等于ceil((mid+1)*q/p)+1
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
/* --------------- fast io --------------- */ // begin
namespace Fread {
const int SIZE = 1 << 21;
char buf[SIZE], *S, *T;
inline char getchar() {
if (S == T) {
T = (S = buf) + fread(buf, 1, SIZE, stdin);
if (S == T) return '\n';
}
return *S++;
}
} // namespace Fread
namespace Fwrite {
const int SIZE = 1 << 21;
char buf[SIZE], *S = buf, *T = buf + SIZE;
inline void flush() {
fwrite(buf, 1, S - buf, stdout);
S = buf;
}
inline void putchar(char c) {
*S++ = c;
if (S == T) flush();
}
struct NTR {
~ NTR() { flush(); }
} ztr;
} // namespace Fwrite
#ifdef ONLINE_JUDGE
#define getchar Fread :: getchar
#define putchar Fwrite :: putchar
#endif
namespace Fastio {
struct Reader {
template<typename T>
Reader& operator >> (T& x) {
char c = getchar();
T f = 1;
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
x = 0;
while (c >= '0' && c <= '9') {
x = x * 10 + (c - '0');
c = getchar();
}
x *= f;
return *this;
}
Reader& operator >> (char& c) {
c = getchar();
while (c == ' ' || c == '\n') c = getchar();
return *this;
}
Reader& operator >> (char* str) {
int len = 0;
char c = getchar();
while (c == ' ' || c == '\n') c = getchar();
while (c != ' ' && c != '\n' && c != '\r') { // \r\n in windows
str[len++] = c;
c = getchar();
}
str[len] = '\0';
return *this;
}
Reader(){}
} cin;
const char endl = '\n';
struct Writer {
template<typename T>
Writer& operator << (T x) {
if (x == 0) { putchar('0'); return *this; }
if (x < 0) { putchar('-'); x = -x; }
static int sta[45];
int top = 0;
while (x) { sta[++top] = x % 10; x /= 10; }
while (top) { putchar(sta[top] + '0'); --top; }
return *this;
}
Writer& operator << (char c) {
putchar(c);
return *this;
}
Writer& operator << (char* str) {
int cur = 0;
while (str[cur]) putchar(str[cur++]);
return *this;
}
Writer& operator << (const char* str) {
int cur = 0;
while (str[cur]) putchar(str[cur++]);
return *this;
}
Writer(){}
} cout;
} // namespace Fastio
#define cin Fastio :: cin
#define cout Fastio :: cout
#define endl Fastio :: endl
/* --------------- fast io --------------- */ // end
int t;
signed main()
{
cin>>t;
while(t--){
int p,q,k;
int ans=0;
cin>>p>>q>>k;
if (p==q){
if (k==1) cout<<0<<"\n";
else cout<<-1<<"\n";
}
else if (p<q) cout<<-1<<"\n";
else{
int l=0,r=1e18;
while(l<=r){
int mid=l+r>>1;
__int128 check=((__int128)(mid+1)*q-1)/p;
if (mid+1-check>=k){
r=mid-1;
ans=mid;
}
else{
l=mid+1;
}
}
cout<<ans<<"\n";
}
}
return 0;
}
T2
小 D 有一座城堡。城堡里面有 n 个房间,每个房间上都写着一个数字 pi。
小 D 拉着几个小伙伴在城堡里面玩耍,他们约定:如果某个人当前站在 i 房间里面,下一步这个人就会去 pi 房间,再下一步这个人去 ppi…
为了增加趣味性,小 D 想重新书写每个房间的 pi,以满足:
如果从编号 1 到 k 中的某个房间开始,按照规则走,必须能够走到 1 号房间。 特别地,如果从 1 号房间开始走,也要能够走回 1 号房间(至少走一步,如果 p1=1,从 1 走到 1 也算合法)。
如果从编号大于 k 的某个房间开始,按照规则走,一定不能走到 1 号房间。
小 D 想知道,有多少种书写 pi 的方案,可以满足要求。答案对 10^9+7 取模。
思路
有n个点,每个点有一条出边。要求前k个点能走到1号点,后n-k个点不能走到一号点,问方案数。
要爆搜前k个点连接的方案,然后检查;后(n-k)个点,只要连的是后(n-k)个点,爱怎么连怎么连,方案数是 (n-k)^n-k。 最后把两部分方案数乘起来就行。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=20;
const int mod=1e9+7;
int n,k,p[N],ans;
bool b[N];
int ksm(int a,int b){
int ans=1;
while(b){
if (b&1){
ans=(ans*a)%mod;
}
b>>=1;
a=(a*a)%mod;
}
return ans;
}
bool check(){
for (int i=1;i<=k;i++){
int j=i;
memset(b,0,sizeof b);
while(j!=1){
if (b[j]) break;
b[j]=true;
j=p[j];
}
if (j!=1) return false;
}
return true;
}
void dfs(int x){
if (x==k+1){
ans=ans+check();
return;
}
for (int i=1;i<=k;i++){
p[x]=i;
dfs(x+1);
}
}
signed main()
{
cin>>n>>k;
int lf=ksm(n-k,n-k)%mod;
dfs(1);
cout<<(ans%mod*lf)%mod;
return 0;
}
T4
滤过