全世界都会莫比乌斯反演系列……
补题进度[3/12] 场上2题
1001 oval-and-rectangle
先把式子写出来,然后强行手算积分,最后把结果一输出就行了……不知道出题人出这个题的意图是什么。
1012 Pinball
由于不会各种牛逼的坐标系建系方法,所以采用了最原始的受力分解+运动分解。公式都写在代码里了
核心思想就是我们把速度和重力按照方向分解,发现可以分解成沿斜面的运动和在斜面上的平抛运动,答案就等于在运动到终点的时候,能进行平抛多少次。
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define G 9.8
using namespace std;
const double pi = acos(-1);
int main()
{
int T;
double b,a,x,y;
cin>>T;
while(T--)
{
cin>>a>>b>>x>>y;
double th = atan(b/a);
//cout<
//th *= pi;
x = -x;
double ay = G*cos(th);
double ax = G*sin(th);
//cout<
double L = x / cos(th);
double h = y - (b/a)*x;
//cout<
double v0 = sqrt(2*G*h);
double vt = sin(th)*v0;
double vh = cos(th)*v0;
double t = 2*(vh/ay);
//double l = t*vt;
double T = (sqrt(2*ax*L + vt*vt)-vt)/ax;
//cout<
//cout<
cout<<floor(T/t) + 1<return 0;
}
1007 Werewolf
提议就是简化版的狼人杀,只有狼人和村民两个角色。狼人可能说谎,村民一定说实话。问肯定是村民或者肯定是狼人的人数有多少个。
既然狼人可能说谎的话,那么所有的人都有可能是狼人,也就是说我们根本无法确定有多少人是村民。答案1就是0
那我们将方向集中在确定哪些人是狼。我们把一个人说另一个人的身份这个关系当成一个边,然后我们先把村民边(A说B是村民)建立反向边,然后里用并查集找狼人边是否成环,记录下成环的这个点,之后跑一边bfs,沿着反向边,将所有人都放进队列。最后的答案就是有多少个人被标记了,或者可以记录有多少个人入队。
为什么这样做呢。我们首先不考虑狼人边,如果一条村民边形成的链:A-B-C-D,现在D说B是狼,那么假如A是村民,也就是说BCD都是村民,但是D说B是狼,所以可以确认的是B肯定不是村民,因为以他和其之后的村民链是矛盾的。此时A知道B是狼,但是他说谎了,所以他也一定是不是村民。这就是为什么要建反向边的理由,因为这个节点反向边形成的子树全部都肯定是狼,因为他们都说谎了。
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define next fuck
#define G 9.8
using namespace std;
const double pi = acos(-1);
const int maxn =1e5 + 5;
int f[maxn];
int Find(int x)
{
//sz[x]++;
return f[x] == x ? x : f[x] = Find(f[x]);
}
vector<int> edge[maxn];
int next[maxn],v[maxn],vis[maxn];
int mark[maxn];
void init(int n)
{
for(int i = 1;i<=n;i++) f[i]= i,vis[i] = 0,mark[i]= 0 ,edge[i].clear();
}
int main()
{
int T;
int n;
char op[20];
int t;
scanf("%d",&T);
queue<int> q;
while(T--)
{
scanf("%d",&n);
init(n);
for(int i = 1;i<=n;i++)
{
scanf("%d %s",&v[i],op);
vis[i] = (op[0] == 'v');
if(vis[i])
{
edge[v[i]].push_back(i);
//vis[v[i]] = 1;
f[i]= f[Find(v[i])];
}
while(!q.empty()) q.pop();
for(int i = 1;i<=n;i++)
{
if(!vis[i])
{
int fa = Find(i);
int fb = Find(v[i]);
if(fa != fb) continue;
q.push(v[i]);
mark[v[i]]= 1;
}
}
int ans =0;
while(!q.empty())
{
int u = q.front();
q.pop();
ans++;
for(int v : edge[u])
{
if(!mark[v])
{
q.push(v);
mark[v] = 1;
}
}
}
printf("0 %d\n",ans);
}
return 0;
}
1002 bookshelf
这道题就是那道反演,做法具体就是枚举下GCD,然后计数一下,最后注意要对fib-number取模1e9+6
怎么推的式子以后再补上吧
#include
using namespace std;
#define ll long long
#define next fuck
const int MAXN = 1e6 + 10;
const ll mod = 1e9+7;
ll inv[2*MAXN],fac[2*MAXN];
void init() //o(n)的组合数
{
inv[0]=fac[0]=1;
inv[1]=1;
for(int i=1; i<2*MAXN; i++)
fac[i]=fac[i-1]*i%mod;
inv[1]=1;
for(int i=2; i<2*MAXN; i++)
inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
inv[0]=1;
for(int i=1; i<2*MAXN; i++)
inv[i]=inv[i-1]*inv[i]%mod;
}
ll com(int n,int m)
{
//if(n <0 || m <0 || m > n) return 0;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
bool check[MAXN+10];
int prime[MAXN+10];
int mu[MAXN+10];
void Mobius()
{
memset(check,false,sizeof(check));
mu[1] = 1;
int tot = 0;
for(int i = 2; i <= MAXN; i++)
{
if( !check[i] )
{
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot; j++)
{
if(i * prime[j] > MAXN)
break;
check[i * prime[j]] = true;
if( i % prime[j] == 0)
{
mu[i * prime[j]] = 0;
break;
}
else
{
mu[i * prime[j]] = -mu[i];
}
}
}
}
ll pow_mod(ll a,ll n)
{
ll res = 1,b = a % mod;
while(n)
{
if(n & 1) res = res * b % mod;
b = b * b % mod;
n >>= 1;
}
return res;
}
vector d;
ll f[MAXN+10],fib[MAXN+10];
int main()
{
int ca,n,k;
Mobius();
init();
fib[0] = 0,fib[1] = 1;
for(int i =2;i<=MAXN;i++)
{
fib[i] = (fib[i-1] + fib[i-2])% (mod-1);
}
scanf("%d",&ca);
while(ca--)
{
scanf("%d%d",&n,&k);
d.clear();
for(int i = 1;i<=n;i++) if(n % i == 0) d.push_back(i);
memset(f,0,sizeof(f));
for(int i = 0;ifor
(int j = i;jif (d[j] % d[i] == 0)
{
f[i] = ((f[i] + 1LL*mu[d[j]/d[i]]*com(n/d[j]+k-1,n/d[j]))%mod + mod)%mod;
}
}
}
ll ans = 0;
for(int i = 0;i// cout<
ans = (ans + f[i]*(pow_mod(2,fib[d[i]]) -1))% mod ;
//ans = (ans% mod + mod) % mod;
}
ans = ans * pow_mod(com(n+k-1,k-1),mod-2)% mod;
if(ans <0 ) ans = (ans + mod) % mod;
printf("%I64d\n",ans);
}
return 0;
}
你可能感兴趣的:(2018多校题解)